Manage complex state with useReduser hook in React - part 20

Use useReducer to Add Dark Mode to React project


We already learned how to manage state with useState to read and update ui but when react application grows, it becomes difficult to handle. 

Many React developers struggle with state management, and if you have a lot of events to handle for updating every single UI in your web application, then state management logic will take up half of the component's body and it'll be hard to handle them single-handedly.

I'm sure you've heard of the Redux library for this kind of situation, but let me introduce you to useReducer first. Redux is a popular choice for larger React projects, The useReducer hook is a lightweight alternative to managing complex states globally in smaller React projects.

In this article, we'll show you how to make a dark toggle mode that uses the useReducer and useEffect hooks to switch on the dark mode when a button is clicked.

It has some tweaks to learn, but you'll see how it was all worth it in the end.

What is useReducer Hook?

When it's append with use keywords it's a hook in React. Reducer is an alternative solution of useState hook or we could also say it's a more advanced technique for more complex react applications.

The useReducer hook is similar to useState in terms of storing and updating components. It helps to keep track of all state in one place which also let you separate state management and rendering in different places. Simply put, it allows you to exclude all state update codes outside of the component in the reducer method.

The steps of useReducer hook going to take as follows:

 [state, dispatch] = useReducer(reducer, initialState) 

  1. The first value returns the state which holds the current value and the second value in the array is the dispatch function.
  2. The useReducer accepts two arguments; reduce which is a function handling update, and the initial object which holds default value and updates accordingly.

I'm going to expand each value that useReducer accepts and returns.

State that useReducer Returns

The state is used to re-render the component when the state returns a new different value. The useReducer returns current state value which can be a string, number, or object. you can use state keywords or define any of your preferred names it's up to you like you can use task or user, similar to useState.

Dispatch in useReducer

When you want to change the current state and reflect the update on the screen, we use the Dispatch function which is the second argument returned by the useReducer hook.

Dispatch function only accepts an action, which we can define with type property and action name being performed. Dispatch function sends this action to the reducer function for handling which is why we can say it is named dispatch.

Dispatch commonly describe as sending a request from one place to another and in React dispatch sends an action from the component to the reducer function.

When you want to update the data or UI we pass the dispatch function to an event handler.

Action in useReducer

Action describes what changes should be made to the state. We dispatch an action when we want to update the value. Action can hold any primitive value like a string or number but most of the time it is an object. The action object typically contains type property and optionally other fields that may have additional information.

You should consider choosing a type name that should describe the action in a clear way.

What is Reducer in useReducer?

Most of you are familiar with the reduce function in vanilla javascript; it is the same in React but with a few differences.

The reduce method is a higher-order function in vanilla javascript that accepts an array of values and reduces them to a single value. In React, the reducer function takes the dispatching action and the current state as arguments and reduces them to a new state.

React will execute Reducer every time a dispatch function triggers a new action, returning a newly updated state as a result.

You may use the Reducer function in a separate named function or in a separate file; the choice is yours; Just make sure to point at the useReducer hook. All data is going to pass inside this reducer function.

By defining Reducer outside of the component, you ensure that it is not redefined, which means that it is defined over and again with the same name every time the component renders.

initialState:

The initial state is a second argument that Reducer accepts. The initial value store the default value and is used to set the initial value of the state object.

When a component first renders on the screen, the initial value sets the state value, and state updates are dependent on that initial value. You can take it as a placeholder. Any type can be described as an initial value, although objects are most frequently used to store all of the component's state properties.

Dark Mode Toggle in React

I'll demonstrate the dork mode toggle functionality so you can understand how useReducer works.

Similarly to how we imported useState hook, we'll import useReducer from the react library and declare useReducer in the same manner as we used to declare useState hook, but it uses a different method for returning an array. 

 import { useReducer, useEffect } from 'react'

 const DarkThemeToggle = () => {
   const [state, dispatch] = useReducer(reducer, { isDarkMode: false })
   
   return (
    <section>
      <button>
        ...
      </button>
      <p>With dark mode functionality you can give your users a sense of peace.</p>
    </section>
  )
 }
 export default DarkThemeToggle 

The initial state object, isDarkMode,  contains a boolean value that is set to false by default.

We'll use useEffect in the functional component body to check the condition and apply the class to the document's body. I already discussed the useEffect hook with dependencies, so go ahead and familiarise yourself with that.

 useEffect(() => {
    const body = document.body
    body.className = state.isDarkMode ? 'dark' : 'light'
  }, [state.isDarkMode]) 

Here is the CSS code for the document's body element with the classes .dark and .light.

.dark {
  background: #111;
  color: #fff;
}
.light {
  background-color: #fff;
  color: #000;
} 

To access or render the value of any property we use state.propertyName, for instance, we have isDarkMode state object, for reading the value of that property we can use state.isDarkMode.

To update the theme we need to dispatch an action. Dispatch function is kind of the same as setState when it comes to updating the state but the approach is different, instead of changing the state directly you'll dispatch an action.

const handleModeClick = () => {
  dispatch({ type: 'dark_mode_active' })
} 

We then render a button's text for the dark mode based on a boolean value that determines whether it's true or false. We used the ternary operator to check the condition and an onClick event handler to dispatch the dark_mode_active action.

 <button onClick={handleModeClick}>
    {state.isDarkMode ? 'Light Mode' : 'Dark Mode'
 </button> 

When the button is pressed, the dispatch function triggers the reducer.

Next, write a reducer function that receives the dispatching action and the current state as arguments and returns a new state.

const reducer = (state, action) => {
  switch(action.type) {
    case 'dark_mode_active': {
      return {
        ...state,
        isDarkMode: !state.isDarkMode,
      };
    }  
    default: return state
  }
} 

In Reducer, we frequently used switch statements to check the type property of action objects, and if the type is dark_mode_active, Reducer returns a new state object with the isDarkMode initial property set to the opposite value in the current state.

Conclusion

Introduction of hooks in React made it easy to work with function components. The useReducer is one valuable addition that is similar to States but it lets you manage complex state logic into a single function outside of the component.

In this tutorial, we learned how to create dark mode functionality in a React project using useReducer. When a user clicks a button, useReducer invokes the reducer function and dispatches an action with the type dark_mode_toggle. The reducer function changes the value of isDarkMode and re-renders the component.

If you have a component that expands in complexity, this article will walk you through the process of moving the state login in the reducer function step by step.


Tell me about how you're managing your state in the comment box.


0 Comments:

Post a Comment