{"id":15311766,"url":"https://github.com/aslemammad/use-context-selector","last_synced_at":"2025-10-08T21:30:33.644Z","repository":{"id":105998071,"uuid":"318099752","full_name":"Aslemammad/use-context-selector","owner":"Aslemammad","description":"React useContextSelector hook in userland","archived":false,"fork":true,"pushed_at":"2020-12-03T07:49:37.000Z","size":1774,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-22T09:31:15.723Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/use-context-selector","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"dai-shi/use-context-selector","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Aslemammad.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}},"created_at":"2020-12-03T06:38:26.000Z","updated_at":"2022-02-08T09:03:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"8527d6aa-1e45-46f4-beba-b05d976cbbe5","html_url":"https://github.com/Aslemammad/use-context-selector","commit_stats":{"total_commits":124,"total_committers":6,"mean_commits":"20.666666666666668","dds":"0.12903225806451613","last_synced_commit":"ace3a81b89dc050be5850a8792a20b8f9b9cb32c"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aslemammad%2Fuse-context-selector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aslemammad%2Fuse-context-selector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aslemammad%2Fuse-context-selector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aslemammad%2Fuse-context-selector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Aslemammad","download_url":"https://codeload.github.com/Aslemammad/use-context-selector/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235761808,"owners_count":19041411,"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":[],"created_at":"2024-10-01T08:34:28.177Z","updated_at":"2025-10-08T21:30:33.213Z","avatar_url":"https://github.com/Aslemammad.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# use-context-selector\n\n[![CI](https://img.shields.io/github/workflow/status/dai-shi/use-context-selector/CI)](https://github.com/dai-shi/use-context-selector/actions?query=workflow%3ACI)\n[![npm](https://img.shields.io/npm/v/use-context-selector)](https://www.npmjs.com/package/use-context-selector)\n[![size](https://img.shields.io/bundlephobia/minzip/use-context-selector)](https://bundlephobia.com/result?p=use-context-selector)\n\nReact useContextSelector hook in userland\n\n## Introduction\n\nReact Context and useContext is often used to avoid prop drilling,\nhowever it's known that there's a performance issue.\nWhen a context value is changed, all components that useContext\nwill re-render.\n\nTo solve this issue,\n[useContextSelector](https://github.com/reactjs/rfcs/pull/119)\nis proposed and later proposed\n[Speculative Mode](https://github.com/reactjs/rfcs/pull/150)\nwith context selector support.\nThis library provides the API in userland.\n\nPrior to v1.3, it uses `changedBits=0` feature to stop propagation,\nv1.3 no longer depends on this undocumented feature.\n\n## Install\n\n```bash\nnpm install use-context-selector\n```\n\n## Technical memo\n\nTo make it work like original React context, it uses\n[useReducer cheat mode](https://overreacted.io/a-complete-guide-to-useeffect/#why-usereducer-is-the-cheat-mode-of-hooks) intentionally.\nIt also requires `useContextUpdate` to behave better in Concurrent Mode.\n(You don't need to use it in Legacy Mode.)\n\n## Usage\n\n```javascript\nimport React, { useState } from 'react';\nimport ReactDOM from 'react-dom';\n\nimport { createContext, useContextSelector } from 'use-context-selector';\n\nconst context = createContext(null);\n\nconst Counter1 = () =\u003e {\n  const count1 = useContextSelector(context, v =\u003e v[0].count1);\n  const setState = useContextSelector(context, v =\u003e v[1]);\n  const increment = () =\u003e setState(s =\u003e ({\n    ...s,\n    count1: s.count1 + 1,\n  }));\n  return (\n    \u003cdiv\u003e\n      \u003cspan\u003eCount1: {count1}\u003c/span\u003e\n      \u003cbutton type=\"button\" onClick={increment}\u003e+1\u003c/button\u003e\n      {Math.random()}\n    \u003c/div\u003e\n  );\n};\n\nconst Counter2 = () =\u003e {\n  const count2 = useContextSelector(context, v =\u003e v[0].count2);\n  const setState = useContextSelector(context, v =\u003e v[1]);\n  const increment = () =\u003e setState(s =\u003e ({\n    ...s,\n    count2: s.count2 + 1,\n  }));\n  return (\n    \u003cdiv\u003e\n      \u003cspan\u003eCount2: {count2}\u003c/span\u003e\n      \u003cbutton type=\"button\" onClick={increment}\u003e+1\u003c/button\u003e\n      {Math.random()}\n    \u003c/div\u003e\n  );\n};\n\nconst StateProvider = ({ children }) =\u003e {\n  const [state, setState] = useState({ count1: 0, count2: 0 });\n  return (\n    \u003ccontext.Provider value={[state, setState]}\u003e\n      {children}\n    \u003c/context.Provider\u003e\n  );\n};\n\nconst App = () =\u003e (\n  \u003cStateProvider\u003e\n    \u003cCounter1 /\u003e\n    \u003cCounter2 /\u003e\n  \u003c/StateProvider\u003e\n);\n\nReactDOM.render(\u003cApp /\u003e, document.getElementById('app'));\n```\n\n## API\n\n\u003c!-- Generated by documentation.js. Update this documentation by updating the source code. --\u003e\n\n### createContext\n\nThis creates a special context for `useContextSelector`.\n\n#### Parameters\n\n-   `defaultValue` **Value** \n\n#### Examples\n\n```javascript\nimport { createContext } from 'use-context-selector';\n\nconst PersonContext = createContext({ firstName: '', familyName: '' });\n```\n\n### useContextSelector\n\nThis hook returns context selected value by selector.\n\nIt will only accept context created by `createContext`.\nIt will trigger re-render if only the selected value is referentially changed.\n\nThe selector should return referentially equal result for same input for better performance.\n\n#### Parameters\n\n-   `context` **Context\u0026lt;Value\u003e** \n-   `selector` **function (value: Value): Selected** \n\n#### Examples\n\n```javascript\nimport { useContextSelector } from 'use-context-selector';\n\nconst firstName = useContextSelector(PersonContext, state =\u003e state.firstName);\n```\n\n### useContext\n\nThis hook returns the entire context value.\nUse this instead of React.useContext for consistent behavior.\n\n#### Parameters\n\n-   `context` **Context\u0026lt;Value\u003e** \n\n#### Examples\n\n```javascript\nimport { useContext } from 'use-context-selector';\n\nconst person = useContext(PersonContext);\n```\n\n### useContextUpdate\n\nThis hook returns an update function that accepts a thunk function\n\nUse this for a function that will change a value.\n\n#### Parameters\n\n-   `context` **Context\u0026lt;Value\u003e** \n\n#### Examples\n\n```javascript\nimport { useContextUpdate } from 'use-context-selector';\n\nconst update = useContextUpdate();\nupdate(() =\u003e setState(...));\n```\n\n### BridgeProvider\n\nThis is a Provider component for bridging multiple react roots\n\nType: FC\u0026lt;{context: Context\u0026lt;any\u003e, value: any}\u003e\n\n#### Parameters\n\n-   `$0` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** \n    -   `$0.context`  \n    -   `$0.value`  \n    -   `$0.children`  \n\n#### Examples\n\n```javascript\nconst valueToBridge = useBridgeValue(PersonContext);\nreturn (\n  \u003cRenderer\u003e\n    \u003cBridgeProvider context={PersonContext} value={valueToBridge}\u003e\n      {children}\n    \u003c/BridgeProvider\u003e\n  \u003c/Renderer\u003e\n);\n```\n\n### useBridgeValue\n\nThis hook return a value for BridgeProvider\n\n#### Parameters\n\n-   `context` **Context\u0026lt;any\u003e** \n\n## Limitations\n\n-   In order to stop propagation, `children` of a context provider has to be either created outside of the provider or memoized with `React.memo`.\n-   Provider trigger re-renders only if the context value is referentially changed.\n-   Neither context consumers or class components are supported.\n-   The [stale props](https://react-redux.js.org/api/hooks#stale-props-and-zombie-children) issue can't be solved in userland.\n-   Tearing is only avoided within the Provider tree. A value outside the Provider will tear. (`02_tearing_spec` fails)\n\n## Examples\n\nThe [examples](examples) folder contains working examples.\nYou can run one of them with\n\n```bash\nPORT=8080 npm run examples:01_minimal\n```\n\nand open \u003chttp://localhost:8080\u003e in your web browser.\n\nYou can also try them in codesandbox.io:\n[01](https://codesandbox.io/s/github/dai-shi/use-context-selector/tree/master/examples/01_minimal)\n[02](https://codesandbox.io/s/github/dai-shi/use-context-selector/tree/master/examples/02_typescript)\n\n## Related projects\n\n-   [react-tracked](https://github.com/dai-shi/react-tracked)\n-   [reactive-react-redux](https://github.com/dai-shi/reactive-react-redux)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faslemammad%2Fuse-context-selector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faslemammad%2Fuse-context-selector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faslemammad%2Fuse-context-selector/lists"}