{"id":18563285,"url":"https://github.com/compulim/react-wrap-with","last_synced_at":"2025-10-18T22:07:06.383Z","repository":{"id":65828811,"uuid":"600845357","full_name":"compulim/react-wrap-with","owner":"compulim","description":"Wrap a React component in another component by Higher-Order Component.","archived":false,"fork":false,"pushed_at":"2024-04-01T04:41:34.000Z","size":809,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-14T05:53:15.663Z","etag":null,"topics":["context","hoc","hooks","react","react-hooks"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/react-wrap-with/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/compulim.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-12T19:09:37.000Z","updated_at":"2024-05-30T04:11:36.653Z","dependencies_parsed_at":"2024-05-30T04:11:25.202Z","dependency_job_id":"9a2d0053-8880-464c-a3d5-e6628fa106d0","html_url":"https://github.com/compulim/react-wrap-with","commit_stats":{"total_commits":27,"total_committers":2,"mean_commits":13.5,"dds":"0.33333333333333337","last_synced_commit":"3baf65c13842c68fde24eeaafe934a02db81bddf"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compulim%2Freact-wrap-with","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compulim%2Freact-wrap-with/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compulim%2Freact-wrap-with/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compulim%2Freact-wrap-with/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/compulim","download_url":"https://codeload.github.com/compulim/react-wrap-with/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248151429,"owners_count":21056095,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["context","hoc","hooks","react","react-hooks"],"created_at":"2024-11-06T22:12:16.359Z","updated_at":"2025-10-18T22:07:01.326Z","avatar_url":"https://github.com/compulim.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `react-wrap-with`\n\nCreates higher-order component (HOC) for wrapping component in another component. Also reduce code complexity for React Context by mixing components into a new component.\n\n## Background\n\n\u003e This package targets React developers who build reusable components.\n\nWhen 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.\n\n## How to use\n\nThe following samples assumes a theme is set for the whole component via React Context with corresponding provider component and a HOC function.\n\n### Before\n\n```tsx\nimport { createContext } from 'react';\n\nconst ThemeContext = createContext();\n\nconst ThemeProvider = ({ children }) =\u003e \u003cThemeContext.Provider\u003e{children}\u003c/ThemeContext.Provider\u003e;\n\nconst withTheme = Component =\u003e props =\u003e (\n  \u003cThemeProvider\u003e\n    \u003cComponent {...props} /\u003e\n  \u003c/ThemeProvider\u003e\n);\n\nexport { ThemeProvider, withTheme };\n```\n\n### After\n\n```tsx\nimport { createContext } from 'react';\nimport { wrapWith } from 'react-wrap-with';\n\nconst ThemeContext = createContext();\n\nconst ThemeProvider = ({ children }) =\u003e \u003cThemeContext.Provider\u003e{children}\u003c/ThemeContext.Provider\u003e;\n\nconst withTheme = wrapWith(ThemeProvider);\n\nexport { ThemeProvider, withTheme };\n```\n\n### Extracting props\n\nLet's assume a prop named `accent` need to be extracted and passed to the `\u003cThemeProvider\u003e` component in the following manner:\n\n```ts\nconst ButtonWithTheme = withTheme(Button);\n\n// `accent` with value of `\"blue\"` will be passed to `\u003cThemeProvider\u003e`, while `text` will be passed to `\u003cButton\u003e`.\nrender(\u003cButtonWithTheme accent=\"blue\" text=\"Submit\" /\u003e);\n```\n\n#### Before\n\n```tsx\nconst ThemeProvider = ({ accent, children }) =\u003e (\n  \u003cThemeContext.Provider value={{ accent }}\u003e{children}\u003c/ThemeContext.Provider\u003e\n);\n\nconst withTheme =\n  Component =\u003e\n  ({ accent, ...props }) =\u003e (\n    // \"accent\" props is extracted and passed to \u003cThemeProvider\u003e only.\n    \u003cThemeProvider accent={accent}\u003e\n      \u003cComponent {...props} /\u003e\n    \u003c/ThemeProvider\u003e\n  );\n```\n\n#### After\n\n```tsx\nimport { Extract, wrapWith } from 'react-wrap-with';\n\nconst ThemeProvider = ({ accent, children }) =\u003e (\n  \u003cThemeContext.Provider value={{ accent }}\u003e{children}\u003c/ThemeContext.Provider\u003e\n);\n\n// Mark \"accent\" prop for extraction.\nconst withTheme = wrapWith(ThemeProvider, { accent: Extract });\n```\n\nProps 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`.\n\n### Spying props\n\nSpying is a useful technique to pass the prop to both the container component and the content component.\n\n#### Before\n\n```tsx\nconst ThemeProvider = ({ accent, children }) =\u003e (\n  \u003cThemeContext.Provider value={{ accent }}\u003e{children}\u003c/ThemeContext.Provider\u003e\n);\n\nconst withTheme = Component =\u003e props =\u003e (\n  // Pass \"accent\" prop to \u003cThemeProvider\u003e without extracting it.\n  \u003cThemeProvider accent={props.accent}\u003e\n    \u003cComponent {...props} /\u003e\n  \u003c/ThemeProvider\u003e\n);\n```\n\n#### After\n\n```tsx\nimport { Spy, wrapWith } from 'react-wrap-with';\n\nconst ThemeProvider = ({ accent, children }) =\u003e (\n  \u003cThemeContext.Provider value={{ accent }}\u003e{children}\u003c/ThemeContext.Provider\u003e\n);\n\n// Mark \"accent\" prop for spying.\nconst withTheme = wrapWith(ThemeProvider, { accent: Spy });\n```\n\nBoth the `\u003cThemeProvider\u003e` and the content component will receive the prop `accent`.\n\n### Initializing props\n\nIf 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.\n\n```tsx\nimport { withProps, wrapWith } from 'react-wrap-with';\n\nconst ThemeProvider = ({ accent, children }) =\u003e (\n  \u003cThemeContext.Provider value={{ accent }}\u003e{children}\u003c/ThemeContext.Provider\u003e\n);\n\nconst BlueThemeProvider = withProps(Theme, { accent: 'blue' });\nconst withBlueTheme = wrapWith(BlueThemeProvider);\n```\n\n### Referencing\n\nRefs are automatically forwarded to the content component. If `{ ref: Extract }` is passed, the `ref` prop will reference the container component instead.\n\nIn TypeScript, you may need to explicitly set the generic types of `forwardRef()` function.\n\n```tsx\ntype Props = { text: string };\n\nconst Button = forwardRef\u003cHTMLButtonElement, Props\u003e(({ text }, ref) =\u003e \u003cbutton ref={ref}\u003e{text}\u003c/button\u003e);\n\nButton.displayName = 'Button';\n```\n\n## Breaking changes\n\n### 0.0.3 - Extract props signature changed\n\n\u003e Related to [pull request #30](https://github.com/compulim/react-wrap-with/pull/30).\n\n```diff\n- wrapWith(Container, {}, 'effect')\n+ wrapWith(Container, { effect: Extract })\n```\n\n### 0.0.3 - Initial props is removed and replaced by `withProps` HOC\n\n\u003e Related to [pull request #35](https://github.com/compulim/react-wrap-with/pull/35).\n\n```diff\n- wrapWith(Container, { effect: 'blink', emphasis: Spy })\n+ wrapWith(\n    withProps(Container, { effect: 'blink' }),\n    { emphasis: Spy }\n  )\n```\n\n### 0.0.3 - No longer accept falsy component type, if falsy is expected, coalesce to `\u003cFragment\u003e` instead\n\n\u003e Related to [pull request #36](https://github.com/compulim/react-wrap-with/pull/36).\n\n```diff\n- wrapWith(undefined)\n+ wrapWith(undefined || Fragment)\n```\n\n## Behaviors\n\n### TypeScript: All containers must have props of `children`\n\nContainers must allow `children` props. This is because container is going to wrap around another component in parent-child relationship.\n\nIf you are seeing the following error in TypeScript, please make sure the container component allow `children` props. `React.PropsWithChildren\u003c\u003e` is a helper type to add `children` to any props. If the component does not have props, use this prop type: `{ children?: ReactNode }`.\n\n```\nArgument of type 'FC\u003cProps\u003e' is not assignable to parameter of type 'false | ComponentType\u003cPropsWithChildren\u003cEmptyProps\u003e\u003e | null | undefined'.\n  Type 'FunctionComponent\u003cProps\u003e' is not assignable to type 'FunctionComponent\u003cPropsWithChildren\u003cEmptyProps\u003e\u003e'.\n    Types of property 'propTypes' are incompatible.\n      ...\n```\n\n## Contributions\n\nLike us? [Star](https://github.com/compulim/react-wrap-with/stargazers) us.\n\nWant to make it better? [File](https://github.com/compulim/react-wrap-with/issues) us an issue.\n\nDon't like something you see? [Submit](https://github.com/compulim/react-wrap-with/pulls) a pull request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompulim%2Freact-wrap-with","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcompulim%2Freact-wrap-with","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompulim%2Freact-wrap-with/lists"}