Manage global state with Recoil.js
Software Development Academy
Posted on June 4, 2021
Video tutorial of this article
So far, we have built small projects. In the prop article, we learn how to pass information from a parent to a child. But what happens if we need to pass information between siblings. You can create the state on the parent and then send it to each child, but at one point, your main component will be full of states that should belong somewhere else.
Enter global state management, a way to create state variables in a separate file that any component can import without receiving data using props.
In this article, we will use Recoil.js, a library created by one Facebook developer working in the React team that is the easiest way to implement global state management.
Intended result
Figure 2: App hierarchy chart. Click the image to zoom it to read the description of each component.
Notes:
- The global state is floating around to denote its independence to the component diagram.
- The state file extensions are
.js
because they are plain JavaScript files instead of React components. - We could have a single JavaScript file for both global state variables, but I want to teach how to import and export variables in different files.
- Each Recoil variable must have its own unique name, even if you have the variables in different files.
Getting started
To work with Recoil, we need to do these steps:
1. Install Recoil
First, we need to install Recoil using NPM inside your project folder.
npm install recoil
2. Set up App.jsx
This step needs to be done in the App.jsx
regardless of where we need to use global state data.
// App.jsx
import { RecoilRoot } from "recoil";
export default function App() {
return (
<div className="App">
<RecoilRoot>
<h1>Pet shop</h1>
</RecoilRoot>
</div>
);
}
-
import { RecoilRoot } from "recoil"
to enable the Recoil library -
<RecoilRoot>
needs to wrap around any parent or child component that may need access to the global state.
3. Export state variables
I'm showing one 1 state file, but this applies to any other state file as well.
// state/userData.js
import { atom } from "recoil";
export const petState = atom({
key: "petState",
default: "No pet choosen",
});
-
import { atom } from "recoil"
: A Recoil atom is a JavaScript Object used to hold the data you want as a global state variable. -
export const petState
To indicate that we will import this variable into other files. -
atom({})
The object that set up this global state variable. Its parameters are:-
key
: The unique id of this state. To avoid confusion, use the same name as the constant. -
default
: The initial value of this state. It can be a string, boolean, array, object, etc.
-
4. Import state variables
I'm showing the Content component, but this applies to the App, Header, and Footer components.
// components/Content.jsx
// Core
import { useRecoilState } from "recoil";
// Internal
import { countState } from "../state/siteSettings";
import { petState } from "../state/userData";
export default function HeaderBar() {
// Global state
const [count, setCount] = useRecoilState(countState);
const [pet, setPet] = useRecoilState(petState);
// Method
function onClear() {
setPet("");
setCount(0);
}
return (
<header className="header">
<span className="pet-choosen">{pet}</span>
<button onClick={onClear}>Clear choice</button>
</header>
);
}
This one is longer but lets take our time to analyze it:
-
import { useRecoilState } from "recoil"
Instead of using React useState to handle a local state, we use Recoil to handle a global state. -
import { petState } from "../state/userData"
Here we import the variable we created in the State file. -
useRecoilState(petState);
instead of usinguseState
we useuseRecoilState
.petState
is the initial value that we imported in the previous step.
You can see that inside the JSX and the function that controls the button, the code is the same as using the useState hook.
Conclusion
Recoil has a key advantage over other global state management libraries: It looks and behaves exactly like React hooks. Thus, making it easy to mix them without needing to learn that much.
If you want to see the finished code, open this link and open the branch global-state.
Additional reading
- Recoil documentation: To learn more tricks that Recoil can do.
- Context API: The current way to do global state management on React. Is not hard to learn, but it does not organize your code as elegantly as Recoil.
- Redux: The original way to handle global state on React. Please do not click on it unless you want to have nightmares. It is the equivalent of the SE module (SDA students understand this inside joke) but on code.
Combining Recoil with React Router DOM
If you have <BrowserRouter>
to handle navigation, it does not matter if Recoil wraps BrowserRouter or the other way around.
// Valid
<div className="App">
<BrowserRouter>
<RecoilRoot>
<Switch>
<Route component={Page} />
</Switch>
</RecoilRoot>
</BrowserRouter>
</div>;
// Also valid
<div className="App">
<RecoilRoot>
<BrowserRouter>
<Switch>
<Route component={Page} />
</Switch>
</BrowserRouter>
</RecoilRoot>
</div>;
Credits
- Cover picture: Photo by Edgar Chaparro on Unsplash
- Video tutorial: RecoilJS - State Management Library For React by Maksim Ivanov.
Posted on June 4, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024