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.
-
atomFamilyallows 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
defaultis 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.
-
selectorFamilyallows 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)