Managing Global State

Some storefront applications demand a way to manage global state. There are many state-management libraries out there that help you do just that, such as Redux and MobX. Salesforce does not endorse one particular state-management library over any other—and you can build a PWA Kit app without using one at all.

You can always provide state information to your components via props, but if you want to use React’s more advanced features for managing state, this guide covers other approaches too.

Using Props

The simplest technique for sharing state among components is to provide that state information via props to a component. That component must be a parent to all the components that need to access the state data. The React docs describe this technique in detail and call it lifting state up.

Using the React Context API

React’s Context API simplifies the process of making data available to a large number of components, without having to manually pass that data through props at each level of your app’s component tree.

React Context Example

Here’s an example of how you might use the React Context API with a component that acts as a wrapper around all of your components to provide them with shared state data.

Start by creating a component called GlobalState that has two context objects:

  1. GlobalStateContext: where you can store global state data.
  2. GlobalDispatchContext: your dispatch function, which returns an updated snapshot of global state through a reducer function.

Each context object comes with a <Provider> component that allows consuming components to subscribe to context changes. Here, the context objects are initialized with the props initialState and dispatch. You get these props when you connect your state with a reducer, using the useReducer Hook. For more information on React Hooks, including how to use them with the Context API, see the official React Hooks reference documentation.

Here’s how you would define and initialize a component that uses the Context API for storing global state in your storefront app:

The AppConfig special component located in app/components/_app-config/index.jsx is where you can initialize your state management system. Here, props.children contains all the components of your app, so that's where you want to add your GlobalState component.

To get the props object you need to initialize it first. Use the React Hook useReducer to create a connected state to your reducer. The useReducer function takes in an initialState object and the reducer imported from the GlobalState component. Next, pass in the connected state and a dispatch function to modify that state.

For example:

Now you can give any component access to your global context data, including the ability to update it. Import GlobalStateContext and GlobalDispatchContext from your GlobalState component and provide those context objects to the useContext() method.

For example:

Using a State-Management Library

You can customize your application to use a state management library by overriding the default AppConfig special component located in app/components/_app-config/index.jsx.

Redux Example

Here's how to set up Redux for your PWA by inside AppConfig. The component has four methods that you need to use:

  1. The restore method is where you create your Redux store with a reducer, initial state, and any middleware.
  2. The freeze method allows you to freeze your state management backend for embedding into the page HTML.
  3. The extraGetPropsArgs method is where you can return any extra arguments that you’d like to inject into getProps methods across the entire app. In this case, we can return the Redux store as an extra argument.
  4. The render method allows you to set up context providers for a state management library. For example, you can use it to wrap the app in a Redux provider.

Here is a brief example showing how to use the methods of AppConfig to set up Redux for your storefront app. In addition to the steps we show here, a complete solution requires you to create your store with a reducer, initial state, and any required middleware.