Design+Code logo

Quick links

Suggested search

CodeSandbox Links

If you haven't, I highly encourage you to follow the first part of this tutorial and fork the starter project for this tutorial. You can also access the complete code of this tutorial, with styling, at https://codesandbox.io/s/usereducer-hook-swkwl.

Create the provider

Back in ShopContext.js , add the shopReducer to the imports from the shopReducer file.

// ShopContext.js

import shopReducer, { initialState } from "./shopReducer";

Now, let's create our provider add the bottom of the ShopContext file. If you remember, a provider allows all its children components to subscribe to the context's changes. The ShopProvider will accept an argument, which is an object of children . Don't forget to export your provider.

// ShopContext.js

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

};

Inside of the provider, we will be using another hook from the React library: the useReducer hook. So let's add it to the imports.

// ShopContext.js

import { createContext, useReducer } from "react";

The useReducer hook is pretty similar to a useState hook. The only difference is that a useReducer requires as arguments a reducer and an initialState , and is preferred when we deal with complex state logic. Moreover, instead of setting a state ( setState ), the useReducer hook will dispatch it, meaning the state will be updated, and all the children listening to that state will be alerted.

// ShopContext.js

export const ShopProvider = ({ children }) => {
  const [state, dispatch] = useReducer(shopReducer, initialState);
};

After adding the useReducer line, we'll need to create three functions inside of the provider: one for each action type we added in our switch statement inside of the reducer. Let's start with the ADDTOCART action.

// ShopContext.js, inside of ShopProvider

const addToCart = (product) => {
  const updatedCart = state.products.concat(product);
	updatePrice(updatedCart)

  dispatch({
    type: "ADD_TO_CART",
    payload: {
      products: updatedCart
    }
  });
};

In the function above, called addToCart , we take one argument, which is a product . Then, taking the state.products variable from useReducer , we are adding the product to the updatedCart variable. At the same time, we'll update the total price of the cart (see function below). Finally, we're dispatching the state using the dispatch from useReducer . We need to pass an object, containing a type ( ADDTOCART ), and a payload , which only contains the updated products array. We'll need to add the function for the action types REMOVEFROMCART and UPDATE_PRICE :

// ShopContext.js, inside of ShopProvider

const removeFromCart = (product) => {
  const updatedCart = state.products.filter(
    (currentProduct) => currentProduct.name !== product.name
  );
	updatePrice(updatedCart)

  dispatch({
    type: "REMOVE_FROM_CART",
    payload: {
      products: updatedCart
    }
  });
};

const updatePrice = (products) => {
  let total = 0;
  products.forEach((product) => (total += product.price));

  dispatch({
    type: "UPDATE_PRICE",
    payload: {
      total
    }
  });
};

Now that we have our functions, let's return something from our ShopProvider. At the bottom of the provider, let's return ShopContext.Provider . Inside of the ShopContext.Provider tags, we'll add the children argument we passed to our provider.

// ShopContext.js, inside of ShopProvider

return <ShopContext.Provider>{children}</ShopContext.Provider>;

Don't forget that a provider always requires a value prop, which is the states and functions you want to be available across your components. Let's create a value object, containing the total, products, and the three functions.

// ShopContext.js, inside of ShopProvider

const value = {
  total: state.total,
  products: state.products,
  addToCart,
  removeFromCart,
};

Let's pass the value as a prop to the ShopContext.Provider tag.

// ShopContext.js, inside of ShopProvider

return <ShopContext.Provider value={value}>{children}</ShopContext.Provider>;

Create the useContext

We're almost there! This is the last step when creating a context, which is creating a useContext hook. Import useContext from the React imports.

// ShopContext.js

import { createContext, useReducer, useContext } from "react";

Create the useShop custom hook, which derives from useContext. Learn more about it in the useContext section of this handbook.

const useShop = () => {
  const context = useContext(ShopContext)

  if (context === undefined) {
    throw new Error("useShop must be used within ShopContext")
  }

  return context
}

export default useShop

Use the provider

In App.js, import ShopProvider from the ShopContext file.

// App.js
import { ShopProvider } from "./ShopContext"

Wrap all the content in ShopProvider tags.

const App = () => {
  return (
    <ShopProvider>
      { /* App content here... */ }
    </ShopProvider>
  );
};

Upcoming

Great! We finished coding our context using useReducer . We also wrapped our entire application in our ShopProvider , ready for all its children components to use the context! In the next section, we'll be adding the functionality to our website - in other words, we'll connect the functions we added in the provider to the frontend. See you in the next section !

Learn with videos and source files. Available to Pro subscribers only.

Purchase includes access to 50+ courses, 320+ premium tutorials, 300+ hours of videos, source files and certificates.

BACK TO

useReducer with useContext Part 1

READ NEXT

useReducer with useContext Part 3

Templates and source code

Download source files

Download the videos and assets to refer and learn offline without interuption.

check

Design template

check

Source code for all sections

check

Video files, ePub and subtitles

Browse all downloads

1

Intro to React Hooks

An overview of React Hooks and the frameworks you can use to build your React application blazingly fast

3:39

2

Create your first React app

Create your first React project from the Terminal and save it on your local computer

4:23

3

React Component

Create your first JSX component using React

2:54

4

Styling in React

How to style your React components using inline styling, separate stylesheets or styled-components

5:06

5

Styles and Props

Render different styles depending on different properties passed to your component

2:22

6

Understanding Hooks

Learn about the basics of React Hooks, which introduced at React Conf 2018

3:21

7

useState Hook

Use the useState hook to manage local state in your React component

2:54

8

useEffect Hook

Manage with your component's lifecycle with the useEffect hook

3:41

9

useRef Hook

Learn about the useRef hook, which replaces the JavaScript getElementById way

3:00

10

Props

Learn about props in React to pass data from parent to child components

3:11

11

Conditional Rendering

Render different UIs depending on different conditions and states

4:21

12

Load Local Data

Load local JSON data into your React application

4:04

13

Fetch Data from an API

Learn the basics of asynchronous functions and promises by fetching data from an API using fetch, useEffect and useState

5:40

14

Toggle a state

Learn how to toggle a state from true to false and back again

4:05

15

useInput Hook

Create a hook to get the value and the onChange event of input fields

6:04

16

Gatsby and React

Create a static content-oriented website using React on Gatsby

6:44

17

NextJS and React

Create your first NextJS React application

5:24

18

React TypeScript Part 1

Learn how to create a React TypeScript application using the Create React App, Gatsby and NextJS methods

8:19

19

React TypeScript Part 2

Learn the basics of TypeScript and how to use TypeScript in a React component

7:35

20

useScrollPosition Hook

Create a custom hook to listen to the current window position of the user

4:26

21

useOnScreen hook

Create a custom hook to listen to when an element is visible on screen

8:08

22

useContext Hook

Manage global states throughout the entire application

8:32

23

Fragments

Group multiple children together with React Fragments

2:43

24

Lazy Loading

Lazy Load heavy components to improve performance

4:05

25

React Suspense

Wait for data with React Suspense and React.lazy

3:13

26

Environment Variables

Make environment variables secret with a .env file

4:43

27

Reach Router

Create a multiple-pages React application with Reach Router

5:31

28

URL Params

Create unique URL with URL Params

4:04

29

SEO and Metadata

Optimize a React application for search engines with React Helmet

6:47

30

Favicon

Add an icon to a React website

3:03

31

Dynamic Favicon

Change the favicon's fill color depending on the user's system appearance

2:14

32

PropTypes

Implement props type-checking with PropTypes

3:54

33

Custom PropTypes

Create a custom PropType using a validator function

3:58

34

useMemo Hook

Prevent unnecessary re-renders when the component stays the same

4:05

35

forwardRef Hook

Forward a ref to a child component

3:28

36

Handling Events

How to handle events in React

5:44

37

Spread attributes

Learn how to make use of the spread operator

3:35

38

useMousePosition Hook

Detect the user's mouse position on a bound element

4:55

39

useReducer with useContext Part 1

Create a reducer to be used in a context

7:33

40

useReducer with useContext Part 2

Incorporate useReducer with useContext

6:48

41

useReducer with useContext Part 3

Connect the context and reducer with the frontend

5:43

42

Netlify

Deploy to production using Netlify

5:08

43

Gatsby Cloud

Deploy to production using Gatsby Cloud

6:19

44

Gatsby Plugin Image

Use gatsby-plugin-image for automatic image resizing, formatting, and higher performance

8:11

45

useOnClickOutside Hook

Toggle a modal visibility with a useOnClickOutside hook

6:32

46

useWindowSize Hook

Create a hook to determine the width and height of the window

4:14

47

usePageBottom hook

Detect if the user scrolled to the bottom of the page

4:48

48

useLocalStorage Hook

Store an item in a browser's local storage

5:27

49

Three.js in React Part 1

Bring your website to life with beautiful 3D objects

17:33

50

Three.js in React Part 2

Bring your website to life with beautiful 3D objects

11:18