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.
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?
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
