Managing individual states in different components can be cumbersome when your app grows large with time. Hence, we need one central point where you can manage your application state.
Thanks to Hooks as they will make our job very easy in setting up the global state.
Let's get started 😎
Step 1️⃣
Set up the state of the application in one single file named State.tsx
or State.jsx
(If you're using JavaScript)
import React, { createContext, useEffect, useReducer } from "react";
import reducer, { initialState } from "./reducer";
const persistedState = localStorage.getItem("persistedState")
? JSON.parse(window.localStorage["persistedState"])
: undefined;
let AppContext = createContext(initialState as any);
function AppContextProvider(props) {
const fullInitialState = {
...initialState,
...persistedState
};
let [state, dispatch] = useReducer(reducer, fullInitialState);
let value = { state, dispatch };
useEffect(() => {
window.localStorage["persistedState"] = JSON.stringify({
loader: state.loader
});
}, [state]);
return (
<AppContext.Provider value={value}>{props.children}</AppContext.Provider>
);
}
let AppContextConsumer = AppContext.Consumer;
export { AppContext, AppContextProvider, AppContextConsumer };
Step 2️⃣
Now, we will create a Reducer (reducer.ts
), which is simply a function that takes previous state and an action and returns the next state.
export const initialState = {
loader: false
};
const reducer = (state, action) => {
switch (action.type) {
case "setLoader": {
return { ...state, loader: action.loader };
}
}
return state;
};
export default reducer;
From the above piece of code, there is a loader
with initial state set to false
. And, we made our reducer know that whenever an action comes with type setLoader
, it takes the previous state and returns the next state.
Step 3️⃣
Now that we have set up our State and Reducer, our next goal would be to enable state management globally in our application. So, wrap your application inside AppContextProvider
. In my case, the root of the application is inside index.tsx
file.
ReactDOM.render(
<AppContextProvider>
<App />
</AppContextProvider>,
document.getElementById("root")
);
That's it! We are all set. 🚀
Let's jump in to an example case where I want to spin and pause a loader. For this, we will be dispatching actions by specifying what action the buttons should perform.
In other words, we will be dispatching the actions by specifying the type setLoader
along with the value you want to pass to the reducer - true
if you want to spin the loader or false
for pausing the loader.
const Home = () => {
const { state, dispatch } = useContext(AppContext);
const handleSpinLoader = () => {
dispatch({ type: "setLoader", loader: true });
};
const handlePauseLoader = () => {
dispatch({ type: "setLoader", loader: false });
};
return (
<IonPage>
<IonContent>
<IonSpinner name="crescent" paused={!state.loader} />
<IonButton onClick={handleSpinLoader}>Spin Loader</IonButton>
<IonButton onClick={handlePauseLoader}>Pause Loader</IonButton>
</IonContent>
</IonPage>
);
};
Whenever you click on the buttons, actions will be dispatched and there by state changes according to the actions.
I created a working example using Codesandbox. Please feel free to check it out and drop your questions or comments if any.
Top comments (0)