What it is
Recoil is a state management library for React that provides a simple and flexible way to share state across components. It allows for fine-grained state updates, derived state, and asynchronous selectors while integrating seamlessly with React's concurrent features.
Recoil uses atoms to represent shared state and selectors to derive or transform state. Components subscribe to atoms or selectors via hooks, automatically re-rendering when state changes. It supports both synchronous and asynchronous derived state.
Installation
npm install recoilGetting started
The smallest useful thing you can do with it, and what each part means.
import { atom } from 'recoil';
export const countState = atom({
key: 'countState', // unique ID
default: 0,
});import { useRecoilState } from 'recoil';
import { countState } from './store';
function Counter() {
const [count, setCount] = useRecoilState(countState);
return (
<div>
<button onClick={() => setCount(count - 1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}Advanced usage
Where the library earns its place over a simpler alternative.
import { selector } from 'recoil';
import { countState } from './store';
export const doubleCountState = selector({
key: 'doubleCountState',
get: ({ get }) => {
const count = get(countState);
return count * 2;
},
});import { selector } from 'recoil';
export const userDataState = selector({
key: 'userDataState',
get: async () => {
const response = await fetch('https://api.example.com/user');
return response.json();
},
});import { atom, selector, useRecoilValue } from 'recoil';
const firstNameState = atom({ key: 'firstName', default: '' });
const lastNameState = atom({ key: 'lastName', default: '' });
const fullNameState = selector({ key: 'fullName', get: ({ get }) => {
return `${get(firstNameState)} ${get(lastNameState)}`;
}});Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Duplicate key error
- Ensure that every atom or selector has a unique `key` string.
- Components not updating
- Check that you are using Recoil hooks (`useRecoilState`, `useRecoilValue`) and not React state for the same value.
- Selector fetch fails
- Handle errors in async selectors using try/catch and consider fallback states.
Best practices
- Use atoms for shared state and selectors for derived or computed state.
- Keep atoms small and focused to avoid unnecessary re-renders.
- Use unique `key` values for all atoms and selectors.
- Leverage asynchronous selectors for data fetching and caching.
- Avoid excessive use of global atoms; local component state is sometimes simpler.
Background
Why it exists, and what it was reacting to.
Recoil was developed by Facebook to address complex state management needs in React applications. It introduces atoms (pieces of state) and selectors (derived or computed state), providing a more declarative and scalable approach compared to prop drilling or using large global stores.
