Recoil vs Redux & MobX: Modern React State Management Explained

Recoil, Facebook’s experimental state‑management library for React, offers a hook‑based, orthogonal approach that reduces overhead compared to Redux and MobX, supports both synchronous and asynchronous selectors, provides utilities like atomFamily and selectorFamily, and integrates seamlessly with React’s concurrent features, making it a promising frontend solution.

ELab Team
ELab Team
ELab Team
Recoil vs Redux & MobX: Modern React State Management Explained

Introduction

This article introduces Recoil, a state‑management library released by Facebook (not an official React library).

Advantages

Avoids the overhead of libraries such as Redux and MobX.

Mitigates the limitations of React Context.

Disadvantages

Currently supports only hooks.

Still experimental; stability is uncertain.

Background: State Management in React

Traditional solutions like Redux and MobX introduce significant overhead and have different programming models. Redux stores state in a single store using immutable objects, while MobX stores state in multiple observable stores that can be mutated directly.

Main Concepts of Recoil

Atoms – Shared State

Atoms are the smallest units of state that components can subscribe to and update, similar to React’s setState.

const todoListState = atom({
  key: 'todoListState', // unique within RecoilRoot
  default: [],
});

Selectors – Derived State (Pure Functions)

Selectors compute derived data from atoms or other selectors. They can be read‑only or read‑write.

const fontSizeLabelState = selector({
  key: 'fontSizeLabelState',
  get: ({get}) => {
    const fontSize = get(fontSizeState);
    const unit = 'px';
    return `${fontSize}${unit}`;
  },
  set: ({get, set}, newValue) => {
    return set('', newValue);
  },
});

Related Hooks

useRecoilValue()

: read an atom or selector. useSetRecoilState(): write to an atom or selector. useRecoilState(): read‑write access to an atom. useResetRecoilState(): reset an atom to its default value.

Async Selectors and Suspense

Selectors can return a Promise for asynchronous data. React Suspense handles the pending state, and errors can be caught by an ErrorBoundary.

const currentUserNameQuery = selector({
  key: 'CurrentUserName',
  get: async ({get}) => {
    const response = await myDBQuery({
      userID: get(currentUserIDState),
    });
    return response.name;
  },
});
function CurrentUserInfo() {
  const userName = useRecoilValue(currentUserNameQuery);
  return <div>{userName}</div>;
}
function MyApp() {
  return (
    <RecoilRoot>
      <React.Suspense fallback={<div>Loading...</div>}>
        <CurrentUserInfo />
      </React.Suspense>
    </RecoilRoot>
  );
}

Alternatively, useRecoilValueLoadable() can be used to manually handle loading, success, and error states.

function UserInfo({userID}) {
  const userNameLoadable = useRecoilValueLoadable(userNameQuery(userID));
  switch (userNameLoadable.state) {
    case 'hasValue':
      return <div>{userNameLoadable.contents}</div>;
    case 'loading':
      return <div>Loading...</div>;
    case 'hasError':
      throw userNameLoadable.contents;
  }
}

Utilities

atomFamily()

: creates a parameterized atom factory.

const elementPositionStateFamily = atomFamily({
  key: 'ElementPosition',
  default: [0, 0],
});
function ElementListItem({elementID}) {
  const position = useRecoilValue(elementPositionStateFamily(elementID));
  return (
    <div>
      Element: {elementID}
      Position: {position}
    </div>
  );
}
selectorFamily()

: creates a parameterized selector factory.

const myMultipliedState = selectorFamily({
  key: 'MyMultipliedNumber',
  get: (multiplier) => ({get}) => {
    return get(myNumberState) * multiplier;
  },
  set: (multiplier) => ({set}, newValue) => {
    set(myNumberState, newValue / multiplier);
  },
});
function MyComponent() {
  const number = useRecoilValue(myNumberState);
  const multipliedNumber = useRecoilValue(myMultipliedState(100));
  return <div>...</div>;
}

Comparison with Hox

Recoil is an experimental project from Facebook, offering many APIs and still under observation.

Hox is maintained by Ant Financial, more stable, and provides a smaller API surface.

Conclusion

Recoil extracts application state into an orthogonal state tree accessed via atoms and selectors. It leverages React’s own state mechanism, fully supports hooks, and integrates with concurrent features such as Suspense, making it a promising modern state‑management framework for frontend development.

References

Recoil documentation

Recoil official site

You Might Not Need Redux – Dan Abramov

YouTube – Recoil overview

MobX documentation (Chinese)

Understanding MobX principles

Do you need MobX or Redux?

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendState ManagementReacthooks
ELab Team
Written by

ELab Team

Sharing fresh technical insights

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.