
Product
Socket for Jira Is Now Available
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.
use-context-selector
Advanced tools
React useContextSelector hook in userland
React Context and useContext is often used to avoid prop drilling, however it's known that there's a performance issue. When a context value is changed, all components that useContext will re-render.
To solve this issue, useContextSelector is proposed and later proposed Speculative Mode with context selector support. This library provides the API in userland.
Prior to v1.3, it uses changedBits=0 feature to stop propagation,
v1.3 no longer depends on this undocumented feature.
This package requires some peer dependencies, which you need to install by yourself.
npm install use-context-selector react scheduler
Notes for library authors:
Please do not forget to keep "peerDependencies" and
note instructions to let users to install peer dependencies.
To make it work like original React context, it uses useReducer cheat mode intentionally.
It also requires useContextUpdate to behave better in concurrent rendering.
Its usage is optional and only required if the default behavior is unexpected.
If you need a simpler solution, you can use useSyncExternalStore without any libraries. See an example.
import { useState } from 'react';
import { createRoot } from 'react-dom/client';
import { createContext, useContextSelector } from 'use-context-selector';
const context = createContext(null);
const Counter1 = () => {
const count1 = useContextSelector(context, (v) => v[0].count1);
const setState = useContextSelector(context, (v) => v[1]);
const increment = () =>
setState((s) => ({
...s,
count1: s.count1 + 1,
}));
return (
<div>
<span>Count1: {count1}</span>
<button type="button" onClick={increment}>
+1
</button>
{Math.random()}
</div>
);
};
const Counter2 = () => {
const count2 = useContextSelector(context, (v) => v[0].count2);
const setState = useContextSelector(context, (v) => v[1]);
const increment = () =>
setState((s) => ({
...s,
count2: s.count2 + 1,
}));
return (
<div>
<span>Count2: {count2}</span>
<button type="button" onClick={increment}>
+1
</button>
{Math.random()}
</div>
);
};
const StateProvider = ({ children }) => (
<context.Provider value={useState({ count1: 0, count2: 0 })}>
{children}
</context.Provider>
);
const App = () => (
<StateProvider>
<Counter1 />
<Counter2 />
</StateProvider>
);
createRoot(document.getElementById('app')).render(<App />);
This creates a special context for useContextSelector.
defaultValue Value import { createContext } from 'use-context-selector';
const PersonContext = createContext({ firstName: '', familyName: '' });
This hook returns context selected value by selector.
It will only accept context created by createContext.
It will trigger re-render if only the selected value is referentially changed.
The selector should return referentially equal result for same input for better performance.
context Context<Value> selector function (value: Value): Selected import { useContextSelector } from 'use-context-selector';
const firstName = useContextSelector(PersonContext, (state) => state.firstName);
This hook returns the entire context value. Use this instead of React.useContext for consistent behavior.
context Context<Value> import { useContext } from 'use-context-selector';
const person = useContext(PersonContext);
This hook returns an update function to wrap an updating function
Use this for a function that will change a value in concurrent rendering in React 18. Otherwise, there's no need to use this hook.
context Context<Value> import { useContextUpdate } from 'use-context-selector';
const update = useContextUpdate();
// Wrap set state function
update(() => setState(...));
// Experimental suspense mode
update(() => setState(...), { suspense: true });
This is a Provider component for bridging multiple react roots
$0 {context: Context<any>, value: any, children: ReactNode}
$0.context $0.value $0.children const valueToBridge = useBridgeValue(PersonContext);
return (
<Renderer>
<BridgeProvider context={PersonContext} value={valueToBridge}>
{children}
</BridgeProvider>
</Renderer>
);
This hook return a value for BridgeProvider
context Context<any> children of a context provider has to be either created outside of the provider or memoized with React.memo.useContextSelector. If you use both props and use-context-selector to pass the same data, they may provide inconsistence data for a brief moment. (02_tearing_spec fails)The examples folder contains working examples. You can run one of them with
PORT=8080 yarn run examples:01_counter
and open http://localhost:8080 in your web browser.
You can also try them in codesandbox.io: 01 02 03
React-Redux is a popular library for managing state in React applications using the Redux pattern. It provides a `connect` function and hooks like `useSelector` and `useDispatch` to connect React components to the Redux store. While `react-redux` is more comprehensive and suited for global state management, `use-context-selector` is more lightweight and focused on optimizing context usage.
Recoil is a state management library for React that provides a way to manage shared state with atoms and selectors. It offers fine-grained control over state updates and dependencies, similar to `use-context-selector`. However, Recoil is more feature-rich and provides a more structured approach to state management compared to the more lightweight `use-context-selector`.
Zustand is a small, fast, and scalable state management solution for React. It uses hooks to manage state and provides a simple API for creating and consuming state. Like `use-context-selector`, it aims to optimize performance by minimizing re-renders, but it is more focused on global state management rather than context-specific optimizations.
FAQs
React useContextSelector hook in userland
The npm package use-context-selector receives a total of 973,759 weekly downloads. As such, use-context-selector popularity was classified as popular.
We found that use-context-selector demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.