Welcome friends. This blog post will teach you how to use the recoil selectors family for state management.
Video for those who understand Hindi: https://youtu.be/GJUq2PkGJWs
How to use Recoil Selectors in Nextjs
🤯Selectors vs SelectorFamily
When you use selectors, you cannot pass any parameters for doing some logical work. But when you use selectors Family, you can pass a param and can have a logic.
Example 👇
🤔Situation
Suppose, you have a to-do list website.
Example of the website:
In simple words, you enter the id of a todo that you want to edit. Then using the recoil selector family, we can get the data of specific todo by passing id as a param.
Then you have made the atoms for it 👇.
import {atom} from 'recoil';
// this atom will store the current input of the user.
export const dataAtom = atom<number>({
key: "data",
default: 1,
});
// this atom will store the list of all todos.
export const todosAtom = atom<
{ userId: number; id: number; title: string; completed: boolean }[]
>({
key: "todos",
default: [
{
userId: 1,
id: 1,
title: "delectus aut autem",
completed: false,
},
{
userId: 1,
id: 2,
title: "quis ut nam facilis et officia qui",
completed: false,
},
{
userId: 1,
id: 3,
title: "fugiat veniam minus",
completed: false,
},
{
userId: 1,
id: 4,
title: "et porro tempora",
completed: true,
},
{
userId: 1,
id: 5,
title: "laboriosam mollitia et enim quasi adipisci quia provident illum",
completed: false,
},
{
userId: 1,
id: 6,
title: "qui ullam ratione quibusdam voluptatem quia omnis",
completed: false,
},
{
userId: 1,
id: 7,
title: "illo expedita consequatur quia in",
completed: false,
},
],
});
Index.tsx file 👇
import type { NextPage } from "next";
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import { dataAtom } from "../atoms/atoms";
import Box from "../components/Box";
const Home: NextPage = () => {
// This will give us ability to get and change the value of the input of the user.
const [data, setData] = useRecoilState<number>(dataAtom);
return (
<div className="flex min-h-screen flex-col items-center justify-center py-2">
<p className="text-md">
Put the id of the todo in inputbox which you want to edit.
</p>
<input
type="number"
className="text-xl outline-none border-2 focus:border-purple-500 p-3 rounded-full duration-150"
placeholder="Enter a value"
value={data}
onChange={(e) => setData(parseInt(e.target.value))}
/>
{/* This is a box component for showing the title of the todo. */}
<Box />
</div>
);
};
export default Home;
This is your selectors file.
import { DefaultValue, selectorFamily } from "recoil";
import { todosAtom } from "../atoms/atoms";
// selector Family
export const todosSelector = selectorFamily({
key: "todosSelect",
// this is return the specific todo when given it's id
get:
(id: number) =>
({ get }) => {
const todos = get(todosAtom);
// id
const todo = todos.find((item) => item.id === id);
return todo;
},
// this will help us set the data of the specific todo
set:
(id: number) =>
({ get, set }, newValue) => {
const todos = get(todosAtom);
const todoIndex = todos.findIndex((item) => item.id === id);
const newTodos = [...todos];
if (newValue instanceof DefaultValue) {
return newTodos[todoIndex];
} else if (newValue === undefined) {
return newTodos[todoIndex];
}
newTodos[todoIndex] = newValue;
set(todosAtom, newTodos);
},
});
Now, let’s go to box.tsx file 👇
import React from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { dataAtom } from "../atoms/atoms";
import { todosSelector } from "../selectors/selectors";
function Box() {
// The current todo id which user has entered
const data = useRecoilValue(dataAtom);
// Data of specific todo
const [todo, setTodo] = useRecoilState(todosSelector(data));
return (
<div className="bg-slate-100 rounded-lg p-5 mt-5">
<h1 className="text-xl mb-2">Todo: {data}</h1>
<input
type="text"
placeholder="title"
value={todo?.title}
// 👇 this function gives us power to change the specific todo data.
onChange={(e) => {
setTodo({
...todo,
title: e.target.value,
} as any);
}}
/>
</div>
);
}
export default Box;
Still any doubt 🤔. You can join our discord channel👇 Join the Next Dev Discord Server!