Global State

Plan: B2B Developer

Lesson 19 of 25 · 15 min

Introduction

In React, each component manages its own local state with hooks like useState. Components can share state by explicitly passing state values as props to other components.

This simplicity works well for shallow component hierarchies, or when only a few pieces of state need to be shared by components that are close together. But as the complexity of a React application grows, the need to share many pieces of state across many components makes prop drilling increasingly impractical.

Let’s explore how the Buyer Portal solves for this state complexity with Redux.

Redux

Redux is a library that exists to solve the very problem we’ve described - the management of complex global state across components.

The Buyer Portal uses Redux throughout the app to manage a number of state values in the user’s session. Examples include:

  • The logged-in user’s company, role, and profile
  • A unique GraphQL authorization token
  • B2B-related config for the store
  • Quote requests in progress

Redux as a whole is a big topic, but the following are central concepts for its use:

  • Immutable state: State is treated as immutable, meaning that new state objects are created with each change, instead of directly updating existing state. The next two bullet points - reducers and actions - are key to this immutability.
  • Reducers: The Redux store uses reducers - pure functions that create a new state object based on the existing state and an input of new state information. (For example, a single reducer might exist for updating the logged-in user’s GraphQL token.)
  • Actions: Instead of simply setting values, component code dispatches explicit actions, which describe what state change is happening and contain a payload of new state information. Actions are the input received by reducers.
  • Selectors: The inverse of actions, selectors are functions that get a specific piece of state from the store.

The Buyer Portal also makes use of Redux Toolkit, an expanded tool set that simplifies many workflows. Key to the Buyer Portal experience is the concept of persistence. Many global state values are not simply stored in React “memory,” but also persisted to the user’s session storage or local storage. This session information can then be automatically rehydrated on new visits to the storefront or new page loads.

Slices

Another key capability enabled by Redux Toolkit is the concept of slices. A slice is a grouping of related state logic, allowing related interfaces, initial state, reducers, and actions to be defined in a central location.

The Buyer Portal organizes its global state into different slices, such as company, global, quoteInfo, etc. The quoteInfo slice, for example, defines interfaces that describe quote-related state, creates the reducers that manage that state, and exports of the actions other code can use to update it.

Redux in the Buyer Portal

The following files and directories are key to the Buyer Portal’s implementation of global state:

  • store/index.ts: Configures the Redux store and exports the hooks components use to manage it.
  • store/reducer.ts: Combines all slice reducers into a root reducer.
  • store/slices/: Individual slices are defined here.
  • store/selectors.ts: Exports common selectors for use throughout the app.

Reading and Updating State

The following simple example demonstrates the core hooks involved with reading and updating state in the Buyer Portal.

import { useAppSelector, useAppDispatch } from "../../../../../../store";
import { setCustomerInfo } from "../../../../../../store/slices/company";
function MyComponent() {
const dispatch = useAppDispatch();
const customer = useAppSelector(({ company }) => company.customer);
const handleUpdate = () => {
dispatch(setCustomerInfo({ ...customer, firstName: "Jane", lastName: "Doe" }));
};
...
}

Selecting state values can be done in an even more deterministic way when a slice exports its own selector functions, which we’ll see in the next lab.

Resources