In Recoil, selectors are pure functions that let you derive, transform, or filter state from atoms (or even other selectors). They don’t store data themselves — instead, they compute it based on existing state, ensuring your UI stays in sync without redundant manual updates.
Why Use a Selector?
Imagine you have an atom that stores raw data (e.g., a list of products). You might need:
- Only filtered products
- A computed total price
- A transformed version of the data
Instead of computing these values in multiple components (which would repeat logic), you centralize the logic inside a selector.
How Selectors Work
- A selector is created using the
selector
function from Recoil. - It has a
get
function to read and compute state. - Optionally, it can have a
set
function to modify underlying atoms when the selector is written to.
Basic Example:
import { atom, selector } from 'recoil';
export const productListState = atom({
key: 'productListState',
default: [
{ name: 'Laptop', price: 1000 },
{ name: 'Phone', price: 500 },
],
});
export const totalPriceSelector = selector({
key: 'totalPriceSelector',
get: ({ get }) => {
const list = get(productListState);
return list.reduce((sum, item) => sum + item.price, 0);
},
});
Here:
-
productListState
is our atom (raw data). -
totalPriceSelector
derives data (sum of prices).
Reading a Selector in a Component
Selectors behave just like atoms when used in components:
import { useRecoilValue } from 'recoil';
import { totalPriceSelector } from './store';
function CartTotal() {
const total = useRecoilValue(totalPriceSelector);
return <div>Total Price: ${total}</div>;
}
Writable Selectors
Selectors can also be writable — meaning you can both read and write.
Example:
export const textState = atom({
key: 'textState',
default: '',
});
export const uppercaseTextSelector = selector({
key: 'uppercaseTextSelector',
get: ({ get }) => get(textState).toUpperCase(),
set: ({ set }, newValue) => {
set(textState, newValue.toLowerCase());
},
});
Key Points to Remember
- Pure Functions: Selectors should not have side effects; they should only depend on other atoms/selectors.
- Automatic Caching: If the underlying atoms don’t change, the selector result is cached.
- Derived State: Use selectors to avoid duplicating computed logic across multiple components.
- Performance Friendly: They recalculate only when their dependencies change.
Top comments (0)