Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
January 8, 2021 03:02 pm GMT

Effective State Management in React using Context API and Hooks!

Hi fellows!

In this blog, I will show you how you can build a simple yet functional state management solution for your React applications. We will use the new Context API along with some useful hooks to build this.

When I first tried out the context API, I was confused as to what is the best way to implement it. Furthermore, I didn't fully understand terms like providers, consumers, reducers etc. that were thrown at me in every online article I read. Thus, I was hesitant in using this simple solution in the applications I built.

It was only recently, that I really understood the concept of Context API and how it can be combined with hooks to build out a pretty powerful state management solution in React. I give all the credit to Brad Traversy for showing how to do this. Hopefully, in this blog post, I will be able to explain it in a very easy and simple way.

Let's get started then!

About the Project

For this blog, we will be building a very simple library application. The idea is not to learn how to build react apps, but how we can use Context API in react. So feel free to copy the code for these components and paste it into your own project. Here's how the final project looks like:

Alt Text

The application consists of 3 components Library, BookShelf, and Book. We want to pass the data to the Book component without passing down props. So, we will use Context API for this.

The entire code for this project can be found on my GitHub: Context-API-Demo

So feel free to reference it if you get stuck.

1. Create A React Application

The first step is to create a basic react application. We will use create-react-app to do this. Just use the following command to create your react project:

npx create-react-app <your_app_name>
Enter fullscreen mode Exit fullscreen mode

Since I will use Bootstrap for styling so you can also add the cdn inside the index.html file as follows:

<link      rel="stylesheet"      href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"      crossorigin="anonymous" />
Enter fullscreen mode Exit fullscreen mode

Great! Now you can open the project in your favorite code editor and move to the second step.

2. Create the Components

Now in the src directory create a folder called components. We will place our component files here. Inside this folder, create the following 3 files:

Library.js

import React from "react";import BookShelf from "./bookShelf";const Library = () => {  return (    <div className="pt-3">      <p>        I am inside the library component.        <span role="img" aria-labelledby="emoji">                  </span>      </p>      <BookShelf />    </div>  );};export default Library;
Enter fullscreen mode Exit fullscreen mode

BookShelf.js

import React from "react";import Book from "./book";const BookShelf = () => {  return (    <React.Fragment>      <p>        I am inside the bookshelf component        <span role="img" aria-labelledby="emoji">                  </span>      </p>      <Book />    </React.Fragment>  );};export default BookShelf;
Enter fullscreen mode Exit fullscreen mode

Book.js

import React, { useContext } from "react";import LibraryContext from "../context/libraryContext";const Book = () => {  return (    <React.Fragment>      <p>        Hi, I am a book inside the bookshelf. My information is coming from the context!        <span role="img" aria-labelledby="emoji">                  </span>      </p>    </React.Fragment>  );};export default Book;
Enter fullscreen mode Exit fullscreen mode

Here we are not doing anything fancy. Just making 3 very basic components. The BookShelf component has the Book component inside it, and the Library has the BookShelf component inside it.

Finally, add the following code to App.js:

import React from "react";import Library from "./components/library";const App = () => {  return (    <React.Fragment>      <div className="container-fluid pt-4 pl-4">        <h2>          React Context API Demo          <span role="img" aria-labelledby="emoji">                      </span>        </h2>        <Library />      </div>    </React.Fragment>  );}export default App;
Enter fullscreen mode Exit fullscreen mode

Here we render the Library component inside the App component. Our component tree looks like this:

Alt Text

3. Implementing Context API

Now comes the fun part: implementing the Context API. First, create a new folder in src called context. I like to keep all the context files in this folder. Inside the folder, we will create 3 files.
These files are: LibraryContext.js, LibraryState.js, and LibraryReducer.js. You can jumble up all these into a single file, but that would become confusing very fast. So, I like to keep all these separate since they handle different functionalities.

First, let's go over how our state management will work. Then we will populate these files.

Library Context

The LibraryContext will create the context and export it. That's it. Nothing more. Here's the code for it:

import { createContext } from "react";// create a contextconst LibraryContext = createContext();export default LibraryContext;
Enter fullscreen mode Exit fullscreen mode

We use the built-in function createContext() to create a context and then we export it as a default export.

Library State

Inside the LibraryState component we will first create our initial state. Then we will use the useReducer hook to add reducers to our initial state. This will give us the dispatch method which can be used to dispatch actions to the reducers.

Let me explain it in easy words: Every time we want to update the state we use dispatch to fire off an action to the reducer. The reducer then updates our state and returns the new state. This pattern is similar to the one used by Redux.

Finally, we return a Provider component which will enable us to access the state anywhere in our application. All we have to do is wrap the component with our LibraryState component and we will get access to the state inside of that component.

Let's look at the code for this:

import React, { useReducer } from "react";import { LibraryReducer } from "./libraryReducer";import LibraryContext from "./libraryContext";// create a provider componentconst LibraryState = (props) => {  // create initial state  const initialState = {    name: "Harry Potter and the Goblet of fire ",    quantity: 7,    shelf: "3A",  };  // useReducer() hook  const [state, dispatch] = useReducer(LibraryReducer, initialState);  // actions to manipulate state  const incrementQuantity = () => {    dispatch({      type: "INCREMENT_QUANTITY",    });  };  const resetQuantity = () => {    dispatch({      type: "RESET_QUANTITY",    });  };  return (    <LibraryContext.Provider      value={{        state: state,        incrementQuantity: incrementQuantity,        resetQuantity: resetQuantity,      }}    >      {props.children}    </LibraryContext.Provider>  );};export default LibraryState;
Enter fullscreen mode Exit fullscreen mode

As you can see we are passing the value inside the Provider which can be accessed by all the components inside of it. In our case, this value includes the state coming from our useReducer and the 2 methods to manipulate that state.

Library Reducer

Inside the LibraryReducer we will create a function that will update the state according to the actions. For every action, it will update the state depending upon the action type. Take a look at the code:

export const LibraryReducer = (state, action) => {  switch (action.type) {    case "INCREMENT_QUANTITY":      return { ...state, quantity: state.quantity + 1 };    case "RESET_QUANTITY":      return { ...state, quantity: 0 };    default:      return state;  }};
Enter fullscreen mode Exit fullscreen mode

Here we are incrementing the count or resetting it depending upon the type of action. As you may recall, we used dispatch to fire off these actions inside the LibraryState component.

4. Accessing State inside Book Component

Now that our context is ready, all we have to do is wrap the Library component inside the LibraryState component which acts as our Provider component. And we will have access to the state inside the Library component and its children.

Head on over to App.js and make the following changes:

Import LibraryState:

import LibraryState from "./context/libraryState";
Enter fullscreen mode Exit fullscreen mode

Wrap Library component:

<LibraryState>  <Library /></LibraryState>
Enter fullscreen mode Exit fullscreen mode

That's it! Now we can access the values from the Provider component anywhere inside the Library component and all its children.

For the last step, we will change the Book component to access the state values and add a couple of buttons to increment or reset the count as well.

Copy and paste the following into the Book component:

import React, { useContext } from "react";import LibraryContext from "../context/libraryContext";const Book = () => {  // useContext() hook  const context = useContext(LibraryContext);  return (    <React.Fragment>      <p>        Hi, I am a book inside the bookshelf. My information is coming from the        context!        <span role="img" aria-labelledby="emoji">                  </span>      </p>      {/* Book Information */}      <p>Book Name: {context.state.name} </p>      <p>Quantity: {context.state.quantity}</p>      <p>Book Shelf: {context.state.shelf}</p>      <div>        <button className="btn btn-primary" onClick={context.incrementQuantity}>          Increment          <span role="img" aria-labelledby="emoji">                      </span>        </button>        <button className="ml-2 btn btn-dark" onClick={context.resetQuantity}>          Reset          <span role="img" aria-labelledby="emoji">                      </span>        </button>      </div>    </React.Fragment>  );};export default Book;
Enter fullscreen mode Exit fullscreen mode

Here we use the useContext hook to pull out the context. Then we access the values inside the context and display them in the component. Since we passed state inside the value of our provider so we access the values as context.state.value.

Finally, we add 2 buttons to increment and reset the count and we add the passed methods as onClick to the buttons.

That's it! The application is now complete. You can see the state values being displayed in the Book component without having to pass down any props whatsoever. And the buttons can be used to manipulate the state as well.

Summary

Here's a quick summary of implementing context:

  • Create the context using the createContext method.
  • Create the Provider component with the values to pass as state.
  • Create reducers to manipulate state and attach with the state using useReducer hook.
  • Wrap the component where value is to be accessed inside the Provider component.
  • Access values using the useContext hook.

Follow me around the web

Some places where you can find me online!

Blog
Twitter
LinkedIn
Dev
GitHub


Original Link: https://dev.to/codewithfahad/effective-state-management-in-react-using-context-api-and-hooks-15ch

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To