Redux Stores
Redux stores are used to maintain global state
ScandiPWA uses Redux to keep track of global state. If used correctly, Redux is predictable and easy to debug.
If you need to keep a state that will be the same throughout the application, and possibly shared between multiple components, create a Redux store. Examples:
Breadcrumbs are stored in a Redux store, because multiple pages need to be able to set them
The Cart is stored in a Redux store, because both the cart overlay and the cart page need to use it, though they don't have a direct parent-child relationship. Also, it is guaranteed that you will need information about only 1 cart in the application.
Avoid using a global Redux store if it is component-specific, and you need to be able to store a different value in each component. Use the component's state instead.
Following Redux practices, the ScandiPWA theme contains 1 Redux store. However, since the application needs to maintain different kinds of global state, the top-level Redux store actually tracks an object containing multiple "sub-stores". Each of these sub-stores, has a dedicated subdirectory in store where it is defined.
The use of Redux stores is not ScandiPWA-specific, so it is best to learn about it from the oficial redux documentation. However, we will go though an example of how it is used in ScandiPWA to help you understand how it interacts with the application.
Example: Breadcrumbs
At the top of many pages in the ScandiPWA theme, you will see breadcrumbs. These are path-like indicators that help the user understand where in the app they currently are, and improve navigation:

Since we would never need to keep track of multiple different breacrumb paths at once, they are implemented in a global redux store. Once a component receives enough data to know what the breadcrumbs should be (such as a list of parent categories as above), it dispatches an update to the breadcrumbs. This state can now be read by the component responsible for rendering breadcrumbs.
1. The .reducer File: Defining the State
.reducer File: Defining the StateSee store/Breadcrumbs/Breadcrumbs.reducer.js.
The first step in creating a redux store is defining what it's initial state should be. We need to keep track of two things - the breadcrumbs themselves and a boolean indicating wether they should be visible on the current page.
Now, we need to describe how the state should update in response to certain actions. It might seem unintuitive at first, but Redux state cannot be updated directly. Instead, you are allowed to define reducers - functions that describe how the state should transition when an action is dispatched.
We want to handle two types of actions - one that updates the breadcrumbs, and one that updates their visibility:
All actions are simple JavaScript objects that carry information which the reducer can interpret to update the state. The UPDATE_BREADCRUMBS action would look like this:
The TOGGLE_BREADCRUMBS would be similar, but carry a different type of data, a boolean:
Note that, by themselves, actions do not do anything - they are just objects with some fields. However, when an action is dispatched ("sent" to Redux, we'll get to that later), Redux passes it on to all reducers (functions we define). Each reducer can look at the action and update its state by returning a new value.
Now that the reducer is defined, we need to include it in our single global Redux state.
2. The .action File: Defining Possible Actions
.action File: Defining Possible ActionsThe reducer we created can respond to certain actions described above, but creating those action object manually would get repetitive and error-prone. Hence, we create functions that can create these action objects for us:
Redux strongly discourages creating side effects in the reducer, or action creators. Avoid making requests, mutating non-Redux state, or other changes in these functions. This will make them less predictable and harder to debug.
3. The .dispatcher File: Dispatching Helpers
.dispatcher File: Dispatching HelpersIt can be convenient to have a file that defines helpers for dispatching actions. That's what the .dispatcher file is for:
Unlike the reducer or action creators, you are free to have side effects in the dispatcher. For example, in store/Cart/Cart.dispatcher.js, addProductToCart makes a GraphQl mutation request before updating the store by dispatching a cart data update.
4. Usage in Components
Any component's container can read and dispatch to the Redux state by using the connect higher-order component.
Reading the state: Example
Dispatching to the state: Example
Last updated
Was this helpful?