When working with React applications, managing dynamic and asynchronous data often becomes complex. Recoil, a state management library for React, offers a powerful duo: atomFamily
and selectorFamily
, which enable developers to manage parameterized state and perform async queries effortlessly.
In this article, we’ll explore how these concepts work together with a practical example: fetching dynamic todos from an API.
1. Understanding atomFamily
- An atom in Recoil is a unit of state that components can subscribe to.
-
atomFamily
allows you to create parameterized atoms, meaning each atom can hold a separate value depending on the parameter passed (like anid
). - This is ideal for scenarios where you need to manage multiple similar states (e.g., todos, users, posts) without manually creating separate atoms for each.
export const todosAtomFamily = atomFamily({
key: "todosAtomFamily",
default: selectorFamily({
key: "todosSelectorFamily",
get: function (id) {
return async function () {
const res = await axios(`https://dummyjson.com/todos/${id}`);
return res.data;
};
},
}),
});
Here:
- Each
todosAtomFamily(id)
represents a unique todo. - The
default
is powered by aselectorFamily
, which fetches data dynamically from the API.
2. Role of selectorFamily
- A selector in Recoil derives data from atoms or other selectors.
-
selectorFamily
allows selectors to be parameterized, so we can query data based on an input (likeid
). - In this case, the selector asynchronously fetches a todo item from
https://dummyjson.com/todos/:id
.
This makes the atom dynamic: the first time you access todosAtomFamily(2)
, it triggers the API call for Todo with ID 2.
3. Integrating into the React App
function App() {
return (
<RecoilRoot>
<Todo id={1} />
<Todo id={2} />
<Todo id={2} />
<Todo id={2} />
<Todo id={2} />
<Todo id={2} />
</RecoilRoot>
);
}
function Todo({ id }) {
const todo = useRecoilValue(todosAtomFamily(id));
return (
<>
{todo.todo}
{todo.completed ? "✅ Completed" : "❌ Not Completed"}
<br />
</>
);
}
-
<Todo id={1} />
fetches and displays Todo with ID1
. - Since Recoil caches atomFamily values, multiple
<Todo id={2} />
components won’t re-fetch from the API; they’ll use the cached data.
4. Why This Matters
✅ Dynamic state: No need to define multiple atoms manually.
✅ Automatic caching: Data for each id
is stored and reused.
✅ Asynchronous fetching: Data is loaded seamlessly using selectors.
✅ Scalability: Works well for lists of items like products, users, or messages.
5. Conclusion
By combining atomFamily
and selectorFamily
, you can elegantly manage dynamic and async state in Recoil. This pattern is especially useful when fetching user-specific or resource-specific data from APIs.
In our todo app, each <Todo />
component only needs an id
, and Recoil handles the rest—fetching, caching, and sharing state across components.
This approach not only reduces boilerplate but also ensures performance and scalability in larger React applications.
Top comments (0)