Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Learn React with TypeScript - Second Edition

You're reading from  Learn React with TypeScript - Second Edition

Product type Book
Published in Mar 2023
Publisher Packt
ISBN-13 9781804614204
Pages 474 pages
Edition 2nd Edition
Languages
Author (1):
Carl Rippon Carl Rippon
Profile icon Carl Rippon

Table of Contents (19) Chapters

Preface 1. Part 1: Introduction
2. Chapter 1: Introducing React 3. Chapter 2: Introducing TypeScript 4. Chapter 3: Setting Up React and TypeScript 5. Chapter 4: Using React Hooks 6. Part 2: App Fundamentals
7. Chapter 5: Approaches to Styling React Frontends 8. Chapter 6: Routing with React Router 9. Chapter 7: Working with Forms 10. Part 3: Data
11. Chapter 8: State Management 12. Chapter 9: Interacting with RESTful APIs 13. Chapter 10: Interacting with GraphQL APIs 14. Part 4: Advanced React
15. Chapter 11: Reusable Components 16. Chapter 12: Unit Testing with Jest and React Testing Library 17. Index 18. Other Books You May Enjoy

State Management

In this chapter, we’ll learn about shared state, which is state that is used by several different components. We will explore three approaches to managing shared state, discussing the pros and cons of each approach.

To do this, we will build a simple app containing a header that displays the user’s name, with the main content also referencing the user’s name. The user’s name will be stored in state that needs to be accessed by several components.

We will start with the simplest state solution. This is to use one of React’s state hooks to store the state and pass it to other components using props. This approach is often referred to as prop drilling.

The second approach we will learn about is a feature in React called context. We will learn how to create a context containing a state and let other components access it.

The last approach we will cover is a popular library called Redux. We will take the time to understand...

Technical requirements

We will use the following technologies in this chapter:

All the code snippets in this chapter can be found online at https://github.com/PacktPublishing/Learn-React-with-TypeScript-2nd-Edition/tree/main/Chapter8.

Creating the project

We will develop our form using Visual Studio Code and a new Create React App-based project setup. We’ve previously covered this several times, so we will not cover the steps in this chapter – instead, see Chapter 3, Setting Up React and TypeScript.

We will style the form with Tailwind CSS. We also previously covered how to install and configure Tailwind in Create React App in Chapter 5, Approaches to Styling Frontends. So, after you have created the React and TypeScript project, install and configure Tailwind.

We will also use the @tailwindcss/forms plugin to style the form. So, install this plugin as well – see Chapter 7, Working with Forms, for information on how to do this.

The app we will build will contain a header and some content beneath it. Here is the component structure we will create:

Figure 8.1 – App component structure

Figure 8.1 – App component structure

The header will have a Sign in button to authenticate and authorize...

Using prop drilling

In this first state management approach, we will store the user, permissions, and loading state in the App component. The App component will then pass this state to the Header and Main components using props.

So, this approach uses React features that we are already aware of. The approach is referred to as prop drilling because the state is passed down the component tree using props.

Carry out the following steps to rework the App component to store the user, permissions, and loading state, and pass this state down to the Header and Main components:

  1. Open App.tsx and start by removing all the existing code and adding the following import statements:
    import { useReducer } from 'react';
    import { Header } from './Header';
    import { Main } from './Main';
    import { authenticate, User } from './api/authenticate';
    import { authorize } from './api/authorize';

We have imported useReducer from React to store the...

Using React context

In this section, we will learn a feature in React called context. We will then refactor the app from the last section to use React context.

Understanding React context

React context is an object that can be accessed by components. This object can contain state values, so it provides a mechanism for sharing state across components.

A context is created using a createContext function as follows:

const SomeContext = createContext<ContextType>(defaultValue);

A default value for the context must be passed into createContext. It also has a generic type parameter for the type that represents the object created by createContext.

The context also contains a Provider component that needs to be placed above components requiring access to the context object in the component tree. A provider wrapper component can be created that stores the shared state and passes it to the context Provider component as follows:

export function SomeProvider({ children...

Using Redux

In this section, we will learn about Redux before using it to refactor the app we have been working on to use it.

Understanding Redux

Redux is a mature state management library that was first released in 2015. It was released before React context and became a popular approach for shared state management.

Creating a store

In Redux, the state lives in a centralized immutable object referred to as a store. There is only a single store for the whole app. Like useReducer, the state in a store is updated by dispatching an action, which is an object containing the type of change and any data required to make the change. An action is handled by a reducer function, which creates a new version of the state.

In the past, a lot of code was needed to set up a Redux store and consume it in a React component. Today, a companion library called Redux Toolkit reduces the code required to use Redux. A Redux store can be created using the Redux Toolkit’s configureStore...

Summary

In this chapter, we built a small one-page app that contained components that needed to share state. We started by using our existing knowledge and used props to pass the state between the components. We learned that a problem with this approach was that components not needing access to the state are forced to access it if its child components do need access to it.

We moved on to learn about React context and refactored the app to use it. We learned that React context can store state using useState or useReducer. The state can then be provided to components in the tree using the context’s Provider component. Components then access the context state via the useContext hook. We found that this was a much nicer solution than passing the state via props, particularly when many components need access to the state.

Next, we learned about Redux, which is similar to React context. A difference is that there can only be a single Redux store containing the state, but there...

Questions

Answer the following questions to check what you have learned in this chapter:

  1. We have a context defined as follows to hold the theme state for an app:
    type Theme = {
      name: string;
      color: 'dark' | 'light';
    };
    type ThemeContextType = Theme & {
      changeTheme: (
        name: string,
        color: 'dark' | 'light'
      ) => void;
    };
    const ThemeContext = createContext<ThemeContextType>();

The code doesn’t compile though; what is the problem?

  1. The context from question 1 has a provider wrapper called ThemeProvider, which is added to the component tree as follows:
    <ThemeProvider>
      <Header />
      <Main />
    </ThemeProvider>
    <Footer />

The theme state is undefined when destructured from useContext in the Footer component. What is the problem?

  1. Is it possible to have two React contexts...

Answers

  1. createContext must be passed a default value when using it with TypeScript. Here’s the corrected code:
    const ThemeContext = createContext<ThemeContextType>({
      name: 'standard',
      color: 'light',
      changeTheme: (name: string, color: 'dark' | 'light') => {},
    });
  2. Footer must be placed inside ThemeProvider as follows:
    <ThemeProvider>
      <Header />
      <Main />
      <Footer />
    </ThemeProvider>
  3. Yes, there is no limit on the number of React contexts in an app.
  4. No, only a single Redux store can be added to an app.
  5. useDispatch can’t be used directly to dispatch an action – it returns a function that can be used to dispatch an action:
    const dispatch = useDispatch();
    function handleChangeTheme({ name, color }: Theme) {
      dispatch(changeThemeAction(name, color));
    }
  6. Yes, local state defined using useState or useReducer...
lock icon The rest of the chapter is locked
You have been reading a chapter from
Learn React with TypeScript - Second Edition
Published in: Mar 2023 Publisher: Packt ISBN-13: 9781804614204
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}