Design+Code logo

Quick links

Suggested search

CodeSandbox Links

You can find the starter project for this tutorial at https://codesandbox.io/s/usereducer-hook-starter-wl8gc . You can also access the complete code of this tutorial, with styling, at https://codesandbox.io/s/usereducer-hook-swkwl.

Understand useContext

Before continuing, you'll need to have a basic concept of the useContext hook. Head over to the useContext section of this handbook to learn more about it. In short, useContext is a hook used to save a state globally, available across the entire application.

Understand useReducer

The useReducer is a hook that allows us to manage complex state logics. If you've used Redux before, the concept of useReducer is pretty similar to Redux. A reducer basically a switch statement defining all the possible actions a context can perform, and only updating the part of the global state related to that action. Now, let's create a useContext hook, using useReducer , with the example of an online shopping website.

Starter Project

For this project, I already created a starter project that you can find at https://codesandbox.io/s/usereducer-hook-starter-wl8gc . If you take a look at it, you'll see that we have a Router in App.js , that links to two different pages: a Products page as well as a Cart page. In the Products component, we are iterating over the shopData array from the ShopData.js file. For each item, we're displaying a ProductCard .

Home page of starter project for useReducer section In the Cart component, we're only displaying a hard-coded text for now with the total price of the cart.

Cart page of starter project for useReducer section We'll be updating this project, so I encourage you to fork that CodeSandbox and we'll create a useContext with useReducer on top of it.

useReducer with useContext Part 1 image 3

Create the context

Now, we'll need to create a context. This context will allow us to access the elements the user added to their cart across the entire application. First, create a ShopContext.js file. We'll import createContext from the React library.

// ShopContext.js

import { createContext } from "react"

Below that, we'll use the createContext function and, as the name implies, create a context. Let's save it in a ShopContext variable.

// ShopContext.js

const ShopContext = createContext();

If you hover over createContext , you'll see that it needs a default value. Let's create the initial value of our context in a shopReducer.js file. We'll need two global states: a total , which will be the total price, and an array of products the user added to their cart. Remember to export that initialState , as we'll need it in ShopContext.js.

// shopReducer.js

export const initialState = {
  total: 0,
  products: []
};

Let's import the initialState in ShopContext.js and pass it as an argument to the createContext function.

// ShopContext.js

import { initialState } from "./ShopReducer";

const ShopContext = createContext(initialState);

Create the reducer

Now that we have the context, we'll create the reducer. In shopReducer.js , right below our initialState, we'll add the following function. It's our reducer, which requires two arguments: a state , which will be a state object, containing the same key-value pairs as our initialState , and an action , which will be an object containing a type of action and a payload . Don't forget to export default the reducer.

// shopReducer.js

const shopReducer = (state, action) => {

}

export default shopReducer

Inside of the reducer, we can extract the type and the payload from the action.

// shopReducer.js

const shopReducer = (state, action) => {
	const { type, payload } = action
}

As mentioned above, a reducer is a switch statement is defining all the possible actions a context can perform, and only updating the part of the global state related to that action. Let's add a switch statement in our reducer. The switch statement will evaluate the type of action provided by the context.

// shopReducer.js

const shopReducer = (state, action) => {
  const { type, payload } = action

	switch (type) {

	}
}

Inside of the switch, let's define a few actions. By convention, each type should be a string, all in uppercase, and each word should be separated by an underscore. This writing format is called SCREAMINGSNAKECASE . For the moment, we'll print the action type as well as the payload on the console. For each case in the switch statement, we'll return the rest of the state, with the updated products or total, depending on the action.

// shopReducer.js

const shopReducer = (state, action) => {
  const { type, payload } = action;

  switch (type) {
    case "ADD_TO_CART":
      console.log("ADD_TO_CART", payload);

      return {
        ...state,
        products: payload.products
      };
    case "REMOVE_FROM_CART":
      console.log("REMOVE_FROM_CART", payload);

      return {
        ...state,
        products: payload.products
      };
    case "UPDATE_PRICE":
      console.log("UPDATE_PRICE", payload);

      return {
        ...state,
        total: payload.total
      };
  }
};

By default, we'll throw an error if the switch statement can't find the type of action provided by the context. It's important to note that this error thrown is for the developer, and shouldn't be seen by the end user. In other words, developers should make sure that all action types are taken care of in the switch statement of the reducer, to prevent any error being thrown to the end user.

// shopReducer.js

const shopReducer = (state, action) => {
  const { type, payload } = action

	switch (type) {
		// Switch cases here...
    default:
      throw new Error(`No case for type ${type} found in shopReducer.`);
  }
}

Upcoming

We coded our reducer! That was easy, wasn't it? In the second part of this three-part tutorial, we'll create our provider and our useContext hook. The context is what will allow us to save the total and the products array states globally. 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

useMousePosition Hook

READ NEXT

useReducer with useContext Part 2

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

Videos

ePub

Assets

Subtitles

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