DEV Community

Cover image for Redux: Beginner's guide
Eric The Coder
Eric The Coder

Posted on • Edited on

Redux: Beginner's guide

Follow me!: Follow @EricTheCoder_


Your app is getting more and more complex?

Over time, your React application becomes more complex, with more app components, and more data going in and out of it. Managing multiple simultaneous components and sub-components state can become very complex.

Is there a better way to manage all yours app components and sub-components state? Yes and that library is name Redux.

What is Redux

Redux is the most popular state management solution. As of today Redux is the standard adopt by big company.

Redux is making use of a redux store, such that the entire application is handled by one state object.

Here are Redux three core principles:

  • The state of your whole application is stored in an object tree within a single store that act as the single source of truth for your app.

  • Ensure the application state is read-only and requires changes to be made by emitting a descriptive action.

  • To specify how the state tree is transformed by actions, you write pure reducer functions.

The entire state of your application is centralized in one location.

So no more props drilling between components and sub components.

No need to send props to child components, or callback functions to parent components.

With Redux you state is now centralized in one location and each component has direct access to the state.

When using Redux, the centralized store is now the only place where state will be change in your application.

State can be change in your store by dispatching different actions. For example an action to add, another action to update, another action to delete, etc.

Install Redux

From an already created React project folder you can type in terminal

$ npm install @reduxjs/toolkit react-redux
Enter fullscreen mode Exit fullscreen mode

create-react-app

If your app is not yet created you can create it with redux store already install and pre-config.

$ npx create-react-app my-app --template redux
Enter fullscreen mode Exit fullscreen mode

Noted. For this tutorial we do not use the create-react-app --template redux

In this tutorial we setup an Redux app from scratch using Redux Toolkit to setup a redux store

Redux DevTools

You can also install a DevToll in your browser that will be handy to debug. For Chrome there is extension call Redux DevTools

How Redux work?

Redux change the way you will code your app. Redux also introduce many new Redux specific terms like store, provider, splice, reducer, selector, action, etc.

Before creating all those elements and make your store work. We need to step back and try to understand the concept as a hole.

The goal we try to achieve is to find a more efficient way to manage the state of all ours components and sub components without using props drilling.

To do that we use Redux. Redux centralize all our state in one place. That centralize place is call the store.

So from now on when you hear the term 'store' that mean your app central place that contain all your components state.

Create a Redux store
The first step is to create your app Redux store.

Create a js file: src/app/store.js and type Redux initialization code.

import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
  reducer: {},
})
Enter fullscreen mode Exit fullscreen mode

This creates a Redux store and for now set the reducer to empty. I will explain reducer a bit later.

Make the store available to React

Once the store is created, we can make it available to our React components by putting a React-Redux Provider around our application in src/index.js.

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import store from './app/store'
import { Provider } from 'react-redux'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)
Enter fullscreen mode Exit fullscreen mode

Import the Redux store we just created, put a Provider around your App, and pass the store as a prop. Now the store is available for all components within the Provider.

Selectors

Since our components state are in a central place we need a way to make call to that store and retrieved state. Redux have a selector hook to help use do just that.

For example in your store you can have a selector name selectItems (we will create that later). That selector for example could return all items in your ecom app basket.

In your component you can use a selector hook to call that store selector and retrieve your items.

import { useSelector } from 'react-redux'
const items = useSelector(selectItems)
Enter fullscreen mode Exit fullscreen mode

That's it. As you can see retrieving state from your store is very easy. Anywhere you are in your component three you can always easily retrieve the state in your store.

Reducers

What about changing the state of items? For example adding or removing items? How can you tell your store that you want to add or remove an item? You will use a store functions name reducer.

Reducer function never mutate the current state. It always return a new updated state object.

For example you can have a reducer function name addItemToBasket. That function will return the new state that include the new item.

In your component you can call reducer function by using the dispatch hook.

import { useDispatch } from 'react-redux'
import { addItemToBasket } from './basketSlice'
const dispatch = useDispatch()

return ( 
  <button onClick={() => dispatch(addItemToBasket(item))}>Add</button>
)
Enter fullscreen mode Exit fullscreen mode

Where and how we declare selectors and reducers?

Selectors and reducers can be create using the createSlice function.

The name โ€œsliceโ€ comes from the idea that we're splitting up your app state into multiple โ€œslicesโ€ of slate.

For example, for an e-commerce app, a slice could be the basket, another one for users, another one for products, etc.

It is a good idea because we need a way to group our selectors and reducers, we cannot put all those functions in one big file. So better group them by slice.

For example if you want to create a basket slice you will create a file: scr/app/features/basketSlice.js

import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  items: [
    {id: 1, name: 'iPhone10'},
    {id: 2, name: 'iPadPro'},
    {id: 3, name: 'iWatch'},
]
};
let nextId = 4
export const basketSlice = createSlice({
  name: 'basket',
  initialState,

  reducers: {
    addItemToBasket: (state, action) => {
      console.log('in')
      state.items = [...state.items, {id: nextId, name: action.payload.name}]
      nextId += 1
    },
    removeItemFromBasket: (state, action) => {
      state.items = state.items.filter(item => item.id !== action.payload.id)
    },
  },
});

export const { addItemToBasket, removeItemFromBasket } = basketSlice.actions;

export const selectItems = (state) => state.basket.items;

export default basketSlice.reducer;

Enter fullscreen mode Exit fullscreen mode

This basket slice contain 2 reducers and one selector.

That's it?

Can we now use those reducers and selectors into your component? Not yet. You need to register the reducer with the store. For that revisite the store.js you create earlier and add the basketSlice reducer.

import { configureStore } from '@reduxjs/toolkit';
import basketReducer from '../features/basket/basketSlice';

export const store = configureStore({
  reducer: {
    basket: basketReducer,
  },
});
Enter fullscreen mode Exit fullscreen mode

Now the basket slice is available to all your app component.

Summary

Ok let's recap:

  • We have a store that contains all our app state.

  • We create our app store in: scr/app/store.js

  • To make that store available to your components We add the Provider tag in between our App top level component

  • To retrieve or mutate data from the store we need to use selectors and reducers.

  • Selectors and reducers are group by app features call slice.

  • To call a selector we use a hook name useSelector(). For example: items = useSelector(basketItems)

  • To call reducer action we use a hook name useDispatch(). For example: dispatch(addItemToBasket(item))

Conclusion

Ouff that's a lot to gaps in one read. If you dont understand everything, that's normal. Read this post more than once and continu your learning on the web with other tutorial.

That's it for today. I still have a lot of posts coming about React so if you want to be sure to miss nothing click follow me!

I am new on twitter so if you want to make me happy
Follow me!: Follow @justericchapman

Top comments (2)

Collapse
 
sm0ke profile image
Sm0ke

Super content ...

Collapse
 
digixvalley profile image
Digixvalley LLC

Really Informative for beginners. <3