loading...

State management using Hooks in Ionic React

chilupa profile image Pavan Chilukuri ・2 min read

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 };

Enter fullscreen mode Exit fullscreen mode

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;

Enter fullscreen mode Exit fullscreen mode

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

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

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.

References

Discussion

pic
Editor guide