DEV Community

Safal Bhandari
Safal Bhandari

Posted on

Asynchronous Data Queries in Recoil with Selectors

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;
    },
  }),
});
Enter fullscreen mode Exit fullscreen mode

🔹 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
    );
  },
});
Enter fullscreen mode Exit fullscreen mode

🔹 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>
  );
}
Enter fullscreen mode Exit fullscreen mode

🔹 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

  1. Asynchronous selectors in Recoil let you fetch API data directly into your state.
  2. This avoids duplicating fetch logic across components.
  3. Derived data (like total notifications) can be computed with selectors without extra API calls.
  4. 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)