DEV Community

TEREN VELAN
TEREN VELAN

Posted on

React Context API & useReducer , Part 1

Today we will learn how to use React Context API to share values across our application and how to use useReducer hook to manage our states within our project.

For the purpose of this post , i will use an e-commerce project as an example. Using React's context API and useReducer to share our state throughout our application and to be able to modify that state throughout our application.

Lets start with React Context API,
For starters we will create the context and assign it to the variable ProductContext. This will create a context object , and every context object comes with a Provider React component that allows consuming components to subscribe to context changes.

//product_context.js

const ProductContext = React.createContext()

Enter fullscreen mode Exit fullscreen mode

But what exactly is "consuming components"? Consuming components are components that are wrapped within the Provider React Component from the context object. In this case we create our own React Component that returns this Provider.

//product_context.js

const ProductContext = React.createContext()

export const ProductsProvider = ({ children }) => {
  return (
    <ProductContext.Provider value={}>
      {children}
    </ProductContext.Provider>
  );
};
Enter fullscreen mode Exit fullscreen mode

Any component that's a children to our ProductsProvider component will be a consuming component of our context and have access to the values that our context provides.

So what are these "values that our context provides" , well , thats up to us to provide any functions or variables that we want our context to provide. In our case we want to pass the fetchProducts function , as shown below.

//product_context.js

export const ProductsProvider = ({ children }) => {

  const fetchProducts = async () => {
    let response = {};
    try {
      response = await axios.get(url);
      let products = response.data;
    } catch (error) {
      console.log({ error });
    }
  };

  return (
    <ProductContext.Provider value={{fetchProducts}}>
      {children}
    </ProductContext.Provider>
  );
};

Enter fullscreen mode Exit fullscreen mode

Within my ProductsProvider component , i have created a function called fetchProducts , which purpose is to fetch data from the API. i then pass that function into the value props of the ProductContext.Provider. As such this value of fetchProducts will be available to all children of ProductContext.Provider.

The last step to access these values from the provider is to use the useContext hook to give access to the values from the ProductContext.Provider.

//product_context.js

export const ProductsProvider = ({ children }) => {

  const fetchProducts = async () => {
    let response = {};
    try {
      response = await axios.get(url);
      let products = response.data;
    } catch (error) {
      console.log({ error });
    }
  };

  return (
    <ProductContext.Provider value={{fetchProducts}}>
      {children}
    </ProductContext.Provider>
  );
};

export const useProductContext = () => {
  return useContext(ProductContext);
};
Enter fullscreen mode Exit fullscreen mode

We create a custom hook called useProductContext thats returns the values from ProductContext.Provider.
As such , when we want to use the values from our context provider , we just have to destructure the values from our custom hook , as shown below.

//Product.js Page

import { useProductContext } from "../products_context";

const { featuredProducts } = useProductContext();

Enter fullscreen mode Exit fullscreen mode

As long as your component is a child component of the ProductsProvider function , your component will have access to these values.

To show and example , i'm using Nextjs for my project and with Nextjs, below is an example of how i would attach my ProductsProvider component , so that my whole application receives the context values.

//_app.js
import { ProductsProvider } from "../products_context";

function MyApp({ Component, pageProps }) {
  return (
      <ProductsProvider>
        <Component {...pageProps} />
      </ProductsProvider>
  );
}

export default MyApp;
Enter fullscreen mode Exit fullscreen mode

In NextJS the tag is the current page that is being displayed , as such every page in my application will have access to my context values.

I hope this gives you a clear picture of the flow of using React Context API. In the part 2 we will look into adding in useReducer to manage the state of our data , and how we share that state value with all our components.

Discussion (0)