# react-wrap-with

> Creates higher-order component for wrapping component in another component.

Latest version **0.2.0** (published 2025-12-22) · MIT license · 0 weekly downloads

## Install

```sh
npm install react-wrap-with
pnpm add react-wrap-with
yarn add react-wrap-with
bun add react-wrap-with
```

## Health

**Score 65/100 (B)** — status: stable.

Positive: has types; esm support; no vulnerabilities; has provenance; high quality score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.2.0 |
| Published | 2025-12-22 |
| First published | 2023-02-12 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 491.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 4 |
| Author | William Wong |
| Maintainers | compulim |
| Keywords | context, higher order, hoc, hook, hooks, provider, react |

## Links

- npm: https://www.npmjs.com/package/react-wrap-with
- Repository: https://github.com/compulim/react-wrap-with
- Homepage: https://github.com/compulim/react-wrap-with#readme
- Issues: https://github.com/compulim/react-wrap-with/issues
- npm.io page: https://npm.io/package/react-wrap-with

## Dependencies (2)

- [type-fest](https://npm.io/package/type-fest.md) ^5.3.1
- [react-wrap-with](https://npm.io/package/react-wrap-with.md) ^0.2.0

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 0.2.0 (latest) — 2025-12-22
- 0.2.1-main.202512312353.fefe50d (main) — 2026-01-01
- 0.2.1-main.202512312301.e17fbaf — 2025-12-31
- 0.2.1-main.202512220619.44e6915 — 2025-12-22
- 0.2.0-main.202512220604.56fd022 — 2025-12-22
- 0.2.0-main.202512220536.0c1b7e7 — 2025-12-22
- 0.2.0-main.62328fb — 2024-12-06
- 0.2.0-main.c5e11e4 — 2024-10-13
- 0.2.0-main.0476d5f — 2024-10-13
- 0.2.0-main.201848c — 2024-10-13
- 0.2.0-main.03ece3a — 2024-10-11
- 0.2.0-main.90ee68f — 2024-06-29
- 0.2.0-main.3be78f3 — 2024-05-31
- 0.2.0-main.8163033 — 2024-05-30
- 0.2.0-main.2a5feda — 2024-05-30
- … 66 more at https://npm.io/package/react-wrap-with/versions

## README

# `react-wrap-with`

Creates higher-order component (HOC) for wrapping component in another component. Also reduce code complexity for React Context by mixing components into a new component.

## Background

> This package targets React developers who build reusable components.

When using React Context or building reusable components, an intermediate component are often needed. This package will help reduce code complexity by wrapping as an intermediate component.

## How to use

The following samples assumes a theme is set for the whole component via React Context with corresponding provider component and a HOC function.

### Before

```tsx
import { createContext } from 'react';

const ThemeContext = createContext();

const ThemeProvider = ({ children }) => <ThemeContext.Provider>{children}</ThemeContext.Provider>;

const withTheme = Component => props => (
  <ThemeProvider>
    <Component {...props} />
  </ThemeProvider>
);

export { ThemeProvider, withTheme };
```

### After

```tsx
import { createContext } from 'react';
import { wrapWith } from 'react-wrap-with';

const ThemeContext = createContext();

const ThemeProvider = ({ children }) => <ThemeContext.Provider>{children}</ThemeContext.Provider>;

const withTheme = wrapWith(ThemeProvider);

export { ThemeProvider, withTheme };
```

### Extracting props

Let's assume a prop named `accent` need to be extracted and passed to the `<ThemeProvider>` component in the following manner:

```ts
const ButtonWithTheme = withTheme(Button);

// `accent` with value of `"blue"` will be passed to `<ThemeProvider>`, while `text` will be passed to `<Button>`.
render(<ButtonWithTheme accent="blue" text="Submit" />);
```

#### Before

```tsx
const ThemeProvider = ({ accent, children }) => (
  <ThemeContext.Provider value={{ accent }}>{children}</ThemeContext.Provider>
);

const withTheme =
  Component =>
  ({ accent, ...props }) => (
    // "accent" props is extracted and passed to <ThemeProvider> only.
    <ThemeProvider accent={accent}>
      <Component {...props} />
    </ThemeProvider>
  );
```

#### After

```tsx
import { Extract, wrapWith } from 'react-wrap-with';

const ThemeProvider = ({ accent, children }) => (
  <ThemeContext.Provider value={{ accent }}>{children}</ThemeContext.Provider>
);

// Mark "accent" prop for extraction.
const withTheme = wrapWith(ThemeProvider, { accent: Extract });
```

Props marked with `Extract` will not be passed to content component. To pass the prop to both the container component and the content component. Please use `Spy`.

### Spying props

Spying is a useful technique to pass the prop to both the container component and the content component.

#### Before

```tsx
const ThemeProvider = ({ accent, children }) => (
  <ThemeContext.Provider value={{ accent }}>{children}</ThemeContext.Provider>
);

const withTheme = Component => props => (
  // Pass "accent" prop to <ThemeProvider> without extracting it.
  <ThemeProvider accent={props.accent}>
    <Component {...props} />
  </ThemeProvider>
);
```

#### After

```tsx
import { Spy, wrapWith } from 'react-wrap-with';

const ThemeProvider = ({ accent, children }) => (
  <ThemeContext.Provider value={{ accent }}>{children}</ThemeContext.Provider>
);

// Mark "accent" prop for spying.
const withTheme = wrapWith(ThemeProvider, { accent: Spy });
```

Both the `<ThemeProvider>` and the content component will receive the prop `accent`.

### Initializing props

If not every props on the container component need to be extracted or spied, the `withProps` HOC can help setting some of the props to a fixed value.

```tsx
import { withProps, wrapWith } from 'react-wrap-with';

const ThemeProvider = ({ accent, children }) => (
  <ThemeContext.Provider value={{ accent }}>{children}</ThemeContext.Provider>
);

const BlueThemeProvider = withProps(Theme, { accent: 'blue' });
const withBlueTheme = wrapWith(BlueThemeProvider);
```

### Referencing

Refs are automatically forwarded to the content component. If `{ ref: Extract }` is passed, the `ref` prop will reference the container component instead.

In TypeScript, you may need to explicitly set the generic types of `forwardRef()` function.

```tsx
type Props = { text: string };

const Button = forwardRef<HTMLButtonElement, Props>(({ text }, ref) => <button ref={ref}>{text}</button>);

Button.displayName = 'Button';
```

## Breaking changes

### 0.0.3 - Extract props signature changed

> Related to [pull request #30](https://github.com/compulim/react-wrap-with/pull/30).

```diff
- wrapWith(Container, {}, 'effect')
+ wrapWith(Container, { effect: Extract })
```

### 0.0.3 - Initial props is removed and replaced by `withProps` HOC

> Related to [pull request #35](https://github.com/compulim/react-wrap-with/pull/35).

```diff
- wrapWith(Container, { effect: 'blink', emphasis: Spy })
+ wrapWith(
    withProps(Container, { effect: 'blink' }),
    { emphasis: Spy }
  )
```

### 0.0.3 - No longer accept falsy component type, if falsy is expected, coalesce to `<Fragment>` instead

> Related to [pull request #36](https://github.com/compulim/react-wrap-with/pull/36).

```diff
- wrapWith(undefined)
+ wrapWith(undefined || Fragment)
```

## Behaviors

### TypeScript: All containers must have props of `children`

Containers must allow `children` props. This is because container is going to wrap around another component in parent-child relationship.

If you are seeing the following error in TypeScript, please make sure the container component allow `children` props. `React.PropsWithChildren<>` is a helper type to add `children` to any props. If the component does not have props, use this prop type: `{ children?: ReactNode }`.

```
Argument of type 'FC<Props>' is not assignable to parameter of type 'false | ComponentType<PropsWithChildren<EmptyProps>> | null | undefined'.
  Type 'FunctionComponent<Props>' is not assignable to type 'FunctionComponent<PropsWithChildren<EmptyProps>>'.
    Types of property 'propTypes' are incompatible.
      ...
```

## Contributions

Like us? [Star](https://github.com/compulim/react-wrap-with/stargazers) us.

Want to make it better? [File](https://github.com/compulim/react-wrap-with/issues) us an issue.

Don't like something you see? [Submit](https://github.com/compulim/react-wrap-with/pulls) a pull request.

---
_Source: https://npm.io/package/react-wrap-with · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
