Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
use-context-selector
Advanced tools
The `use-context-selector` package is a React hook that allows for more granular context updates by enabling the selection of specific parts of the context. This can help optimize performance by reducing unnecessary re-renders in components that consume context.
Context Selection
This feature allows you to select a specific part of the context value, which can help in optimizing performance by preventing unnecessary re-renders of components that consume the context.
```jsx
import React, { createContext } from 'react';
import { useContextSelector } from 'use-context-selector';
const MyContext = createContext();
const MyComponent = () => {
const value = useContextSelector(MyContext, (v) => v.someValue);
return <div>{value}</div>;
};
const App = () => {
const contextValue = { someValue: 'Hello, World!' };
return (
<MyContext.Provider value={contextValue}>
<MyComponent />
</MyContext.Provider>
);
};
export default App;
```
Avoiding Unnecessary Re-renders
This example demonstrates how `use-context-selector` can be used to avoid unnecessary re-renders. The `MyComponent` only re-renders when `someValue` changes, not when `otherValue` changes.
```jsx
import React, { createContext, useState } from 'react';
import { useContextSelector } from 'use-context-selector';
const MyContext = createContext();
const MyComponent = () => {
const value = useContextSelector(MyContext, (v) => v.someValue);
console.log('MyComponent re-rendered');
return <div>{value}</div>;
};
const App = () => {
const [contextValue, setContextValue] = useState({ someValue: 'Hello, World!', otherValue: 42 });
return (
<MyContext.Provider value={contextValue}>
<MyComponent />
<button onClick={() => setContextValue({ ...contextValue, otherValue: contextValue.otherValue + 1 })}>
Update Other Value
</button>
</MyContext.Provider>
);
};
export default App;
```
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.
React useContext with selector support 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.
v1 uses calculateChangedBits=()=>0
technique to stop propagation,
while v2 uses useMutableSource
.
npm install use-context-selector
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
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 }) => {
const [state, setState] = useState({ count1: 0, count2: 0 });
return (
<context.Provider value={[state, setState]}>
{children}
</context.Provider>
);
};
const App = () => (
<StateProvider>
<Counter1 />
<Counter2 />
</StateProvider>
);
ReactDOM.render(<App />, document.getElementById('app'));
In v1:
useContextSelector(context, state => state.count);
In v2:
useContext(context, useCallback(state => state.count, []));
In this case, you can (should) also define the selector function outside render.
This creates a special context for selector-enabled useContext
.
It doesn't pass its value but a ref of the value. Unlike the original context provider, this context provider expects the context value to be immutable and stable.
defaultValue
Valueimport { createContext } from 'use-context-selector';
const PersonContext = createContext({ firstName: '', familyName: '' });
This hook returns context value with optional selector.
It will only accept context created by createContext
.
It will trigger re-render if only the selected value is referentially changed.
The selector must be stable.
Either define selector outside render or wrap with useCallback
.
The selector should return referentially equal result for same input for better performance.
context
Context<Value>selector
function (value: Value): Selected (optional, default identity as(value:Value)=>Selected
)import { useContext } from 'use-context-selector';
const firstName = useContext(PersonContext, state => state.firstName);
A utility function to wrap a callback function with higher priority
Use this for a callback that will change a value, which will be fed into context provider.
callback
Callbackimport { wrapCallbackWithPriority } from 'use-context-selector';
const wrappedCallback = wrapCallbackWithPriority(callback);
children
of a context provider has to be either created outside of the provider or memoized with React.memo
.01_basic_spec
wrapping setState)02_tearing_spec
fails)The examples folder contains working examples. You can run one of them with
PORT=8080 npm run examples:01_minimal
and open http://localhost:8080 in your web browser.
You can also try them in codesandbox.io: 01 02
FAQs
React useContextSelector hook in userland
The npm package use-context-selector receives a total of 300,899 weekly downloads. As such, use-context-selector popularity was classified as popular.
We found that use-context-selector demonstrated a healthy version release cadence and project activity because the last version was released less than 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.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.