When building complex React applications, we often deal with multiple instances of similar pieces of state. Managing each one separately with individual atoms can quickly become messy and repetitive. Recoil provides a powerful utility called atomFamily
to solve this problem.
In this article, we’ll break down what atomFamily
is, why it’s useful, and how it works in the context of a Todo app.
What is atomFamily
?
atomFamily
is a factory function that allows us to create parameterized atoms.
- Instead of writing separate atoms for each todo, we can create one family of atoms.
- Each atom inside the family is uniquely identified by its parameter (like an
id
). - This makes managing dynamic state instances (e.g., multiple todos, users, or chat rooms) simple and scalable.
Example Code Walkthrough
Let’s break down your provided example.
1. Defining the Atom Family
import { atomFamily } from "recoil";
import { TODOS } from "./todos";
export const todosAtomFamily = atomFamily({
key: "todosAtomFamily",
default: (id) => {
return TODOS.find((todo) => todo.id == id);
},
});
-
atomFamily
creates a group of atoms for todos. - Each atom is accessed using
todosAtomFamily(id)
. - The
default
value depends on the givenid
, pulling data from the staticTODOS
array.
This way, each id
corresponds to a unique atom.
2. Using Atoms in Components
function Todo({ id }) {
const todo = useRecoilValue(todosAtomFamily(id));
return (
<>
{todo.title}
{todo.description}
<br />
</>
);
}
-
useRecoilValue(todosAtomFamily(id))
retrieves the specific todo state. - Each
Todo
component renders the title and description for its assignedid
.
3. Updating State
function UpdatedTodo() {
const updateTodo = useSetRecoilState(todosAtomFamily(2));
useEffect(() => {
setTimeout(() => {
updateTodo({
id: "2",
title: "I can change anything",
description: "I am safal",
});
}, 2000);
}, []);
return <div>Hello</div>;
}
-
useSetRecoilState(todosAtomFamily(2))
gives us a setter for the todo withid = 2
. - After 2 seconds, the todo is updated with a new title and description.
- Because all components using
todosAtomFamily(2)
share the same state, they re-render automatically with updated values.
4. Main Application
function App() {
return (
<RecoilRoot>
<Todo id={1} />
<Todo id={2} />
<Todo id={2} />
<Todo id={2} />
<Todo id={2} />
<Todo id={2} />
<UpdatedTodo />
</RecoilRoot>
);
}
- Multiple
<Todo id={2} />
components all subscribe to the same state (todosAtomFamily(2)
). - When
UpdatedTodo
modifies that state, all instances ofid=2
automatically update.
Key Benefits of Using atomFamily
✅ Avoids repetition – no need to manually define separate atoms for each todo.
✅ Dynamic state – you can create atoms on-the-fly using parameters (like id
).
✅ Shared updates – if multiple components reference the same atom, updating it in one place updates all.
✅ Scalable – great for managing lists, collections, or items fetched from APIs.
When to Use atomFamily
?
- Managing state for items with unique identifiers (todos, users, products, etc.).
- Creating multiple instances of the same kind of state dynamically.
- Sharing state across different components that depend on the same key.
Final Thoughts
Recoil’s atomFamily
is one of the most powerful features when working with lists of dynamic data. In this todo example, you’ve seen how easy it becomes to create, read, and update multiple todo items without duplicating state logic.
If your app needs per-item state management, atomFamily
should be your go-to tool.