Skip to main content

Adding state management

This step consists in adding a global state management to the application

note

The core feature of React is to offer components that rerender when a state change.
The state can be the internal state of the component or the state of a parent component (see The Data Flows Down)

onekijs provides a global state for the application to store the data that any component can access and react to. This global state is based on Redux.

Final result

The result of this step is as follows:

New in this step

You can now add a product to the cart by clicking on the "Buy" button available on the product details page.
The "checkout" button is now clickable and displays the cart page

Adding global state management

onekijs provides a store to hold the global state. The store is a Redux store and is automatically started by the <App /> / <NextApp /> component.

note

onekijs provides several hooks to update and react on the global state.
In this tutorial, we will use these hooks:

  • useGlobalState to react on a data of the global state, but also to update it
  • useGlobalProp to only react on a data of the global state

Adding the shopping cart page

This list of products is stored in the global state under the key "cart".
The global state is an immutable javascript object that looks like this:

{
cart: [
{
name: "Phone XL",
price: 799,
description: "A large phone with one of the best screens",
},
{
name: "Phone Standard",
price: 299,
},
];
}

note

By default, the global state is an empty object when the application starts. In our case, this means that the shopping cart page displays an empty list of products.
If necessary, it's possible to pass an initial state to the <App /> / <NextApp /> component.

Add a new page to display the list of products the user wants to buy:

getting-started/cra/step03-global-state/src/pages/cart.tsx
loading...
info

It's a good practice to use a constant to identify a property in the global state. Indeed, if a refactoring is needed further on, it's easier to find which component uses which property.

src/modules/core/libs/constants.ts
export const STATE_CART = 'cart';

The Cart component displays the list of products:
getting-started/cra//step03-global-state/src/modules/core/components/Cart.tsx
loading...

Adding the "Buy" button

Update the product details component to display a button to purchase the product.

getting-started/cra//step03-global-state/src/modules/products/components/ProductDetails.tsx
loading...

Update the product details page to handle the click on the "Buy" button.
A click on the "Buy" button calls a function that adds the product to the "cart" property of the global state.
As the cart page reacts on this property, the product will automatically appears on it.

getting-started/cra/step03-global-state/src/pages/products/%5BproductId%5D/index.tsx
loading...
Immutability

As mentioned above, the global state is immutable. Therefore, to update the cart, you need to use cart.concat() to build a new array and not cart.push().
onekijs transparently handles the immutability of the global state. The cart variable is a standard javascript object that you can manipulate like any other javascript object excepted that it is frozen.

Advanced tip: As the cart variable is immutable, the <Cart/> component could use React.memo to be more efficient

Updating the navigation

Update the main router to add a route to display the cart page
getting-started/cra/step03-global-state/src/pages/_router.tsx
loading...

and finally, update the "Checkout" button to navigate to the cart page

getting-started/cra/step03-global-state/src/modules/core/components/Navbar.tsx
loading...

Next step

Currently, the contents of the cart are only stored in memory (in the global state) and if you refresh the page, the contents are lost.
In the next step, we will add the ability to authenticate a user and then save the cart contents in the cloud.