When building modern React applications, data often comes from APIs rather than being hardcoded. Managing this asynchronous data can get complicated when you need it across multiple components. Recoil provides a simple and efficient way to handle such scenarios using atoms and selectors.
Why Asynchronous Queries in Recoil?
Normally, an atom in Recoil stores some default value (like a string, number, or object). But when we need data from an API, we don’t want to fetch it manually in every component. Instead, we can directly fetch the data inside a selector, and use that as the atom’s default value.
This way:
- Data fetching is centralized.
- Multiple components can read from the same source.
- Recoil automatically caches and updates values.
Example: Fetching Notifications
Let’s consider a scenario where we need to fetch notifications from an API and also calculate the total notifications count.
Step 1: Define the Atom with Asynchronous Selector
import axios from "axios";
import { atom, selector } from "recoil";
// Atom with async default value
export const notifications = atom({
key: "networkAtom",
default: selector({
key: "networkAtomSelector",
get: async () => {
const res = await axios.get("https://nepalak.free.beeceptor.com/get");
return res.data;
},
}),
});
🔹 Here, the notifications
atom doesn’t have a static default value. Instead, its default is another selector that fetches data from the API using axios
.
Step 2: Create a Selector to Derive State
export const totalNotificationSelector = selector({
key: "totalNotificationSelector",
get: ({ get }) => {
const allNotifications = get(notifications);
return (
allNotifications.network +
allNotifications.jobs +
allNotifications.notifications +
allNotifications.messaging
);
},
});
🔹 The totalNotificationSelector
calculates the total number of notifications by reading (get
) from the notifications
atom.
Step 3: Using It in Components
import { useRecoilValue } from "recoil";
import { notifications, totalNotificationSelector } from "./store";
function NotificationPanel() {
const allNotifications = useRecoilValue(notifications);
const total = useRecoilValue(totalNotificationSelector);
return (
<div>
<h2>Notifications</h2>
<p>Network: {allNotifications.network}</p>
<p>Jobs: {allNotifications.jobs}</p>
<p>Messaging: {allNotifications.messaging}</p>
<p>General: {allNotifications.notifications}</p>
<h3>Total: {total}</h3>
</div>
);
}
🔹 Recoil automatically handles the async fetch. If the data is not ready yet, it suspends the component until the data is available (if you are using React Suspense).
Key Takeaways
- Asynchronous selectors in Recoil let you fetch API data directly into your state.
- This avoids duplicating fetch logic across components.
- Derived data (like total notifications) can be computed with selectors without extra API calls.
- Works seamlessly with React Suspense for handling loading states.
✅ Using Recoil’s async selectors makes your React app cleaner, faster, and more maintainable.
Top comments (0)