https://github.com/compulim/react-wrap-with
Wrap a React component in another component by Higher-Order Component.
https://github.com/compulim/react-wrap-with
context hoc hooks react react-hooks
Last synced: about 1 month ago
JSON representation
Wrap a React component in another component by Higher-Order Component.
- Host: GitHub
- URL: https://github.com/compulim/react-wrap-with
- Owner: compulim
- License: mit
- Created: 2023-02-12T19:09:37.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-01T04:41:34.000Z (about 1 year ago)
- Last Synced: 2024-04-14T05:53:15.663Z (about 1 year ago)
- Topics: context, hoc, hooks, react, react-hooks
- Language: TypeScript
- Homepage: https://npmjs.com/package/react-wrap-with/
- Size: 790 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
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 }) => {children};
const withTheme = Component => props => (
);export { ThemeProvider, withTheme };
```### After
```tsx
import { createContext } from 'react';
import { wrapWith } from 'react-wrap-with';const ThemeContext = createContext();
const ThemeProvider = ({ children }) => {children};
const withTheme = wrapWith(ThemeProvider);
export { ThemeProvider, withTheme };
```### Extracting props
Let's assume a prop named `accent` need to be extracted and passed to the `` component in the following manner:
```ts
const ButtonWithTheme = withTheme(Button);// `accent` with value of `"blue"` will be passed to ``, while `text` will be passed to ``.
render();
```#### Before
```tsx
const ThemeProvider = ({ accent, children }) => (
{children}
);const withTheme =
Component =>
({ accent, ...props }) => (
// "accent" props is extracted and passed to only.
);
```#### After
```tsx
import { Extract, wrapWith } from 'react-wrap-with';const ThemeProvider = ({ accent, children }) => (
{children}
);// 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 }) => (
{children}
);const withTheme = Component => props => (
// Pass "accent" prop to without extracting it.
);
```#### After
```tsx
import { Spy, wrapWith } from 'react-wrap-with';const ThemeProvider = ({ accent, children }) => (
{children}
);// Mark "accent" prop for spying.
const withTheme = wrapWith(ThemeProvider, { accent: Spy });
```Both the `` 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 }) => (
{children}
);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(({ text }, ref) => {text});
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 `` 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' is not assignable to parameter of type 'false | ComponentType> | null | undefined'.
Type 'FunctionComponent' is not assignable to type 'FunctionComponent>'.
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.