Setting up Redux Toolkit w/ React JS

Setting up Redux Toolkit w/ React JS

ยท

5 min read

Hey there geeks, we'll be starting a mini-series to understand Redux Toolkit basics and how to get started with setting up Redux Toolkit and start building the project that you always wanted to

Topics covered in this blog

  1. Prerequisites
  2. Bootstrap a React app without any Redux template
  3. Installing and setting up Redux Toolkit
  4. Creating a slice
  5. Configuring the Redux store
  6. Adding multiple slices to the store
  7. Code example
  8. Reference links

Prerequisites

  1. Familiarity with React JS
  2. Basics of Redux ( Actions, Dispatch, Store )

Bootstrapping a React app without any Redux template

In this set up we won't be using the classic create-react-app since it adds a lot of unnecessary dependencies instead we'll be using vite to bootstrap a React JS project which is super fast.

To create a React application run the following command in your terminal after you navigate to the appropriate directory

npm init vite your-app --template react

After the command is executed cd your-app and open the folder in VS Code or any other text editor of your choice. You'll notice that the file structure is mostly the same as create-react-app but the starter code will be a simple counter-example and the entry file is named main.jsx instead of index.js.

Installing and setting up Redux Toolkit

Now that we've got a bootstrapped React application, let's install Redux and start setting it up. You'll have to install the following packages react-redux @reduxjs/toolkit

npm i react-redux @reduxjs/toolkit

now, we can start with setting up Redux. Let's start with creating a folder in the src folder named features. This is where we'll store all the slices for different features of our application.

What Redux recommends today is a feature folder idea. In your application, you pick some concept, and you put all the code related to that feature in one folder, or occasionally even in one file.

Creating a slice ๐Ÿ•

Create a file named counter.slice.js. Obviously, it's a file so you can name it anything you like. In this file, we'll be defining all the reducers for a particular slice of the store. Let's start by importing the createSlice function from the thunkAPI

// src/features/counter/counter.slice.js

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

After we import the createSlice function, we'll configure the slice as below

// src/features/counter/counter.slice.js

const counterSlice = createSlice({
    name: 'counter',
    initialState: {
        count: 0,
    },
    reducers: {
        incrementCounter: (state) => {
            state.count += 1;
        },
        decrementCounter: (state) => {
            state.count -= 1;
        }
    },
});

Here, the name is used to generate actionTypes automatically which will see in a bit. The initialState as the name suggests is the initial state of the slice. And the reducers are the different reducers that you need have to dispatch later on.

While we're at it, we'll also have to export the actions and the reducer like so

// src/features/counter/counter.slice.js

export const { incrementCounter, decrementCounter } = counterSlice.actions;
export default counterSlice.reducer;

Generally, we used to write actionCreators on our own, but now Redux Toolkit automatically does that. It takes the reducers we've defined in the createSlice and generates actions out of it.

{
        type: 'counter/incrementCounter',
} 

// Here `counter` is the name of the slice, so that we can determine which
// action is dispatched from which slice. This is helpful in case we have
// multiple slices with the same action name

// `incrementCounter` is taken directly from the name of the reducer function

If we had a reducer that takes a payload and returns a new state like incrementWithXAmount then the action will be created similar to the code below

{
        type: 'counter/incrementWithXAmount',
        payload: 2, // 2 is the value you pass to the action `incrementWithXAmount(2)`
}

After configuring the slice and exporting the actions and reducer from the slice file, we've to configure the Redux store.

Configuring the Redux store ๐Ÿช

Until now we've configured the slice and created reducers, but we won't be able to use them anywhere if we don't configure the Redux Store. So let's dive right into configuring our store.

Create a new folder src/app and create a new file named store.js in it, here we'll set up the Redux store as follows

// src/app/store.js

import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counter.slice';

export const store = configureStore({
    reducer: {
        counter: counterReducer,
    },
});

An important thing to remember here is that the naming of the slices in the reducer field will matter later on when we'll access the values. In this case, if we want to access the counter value we'll have to write state.counter.value, if the counterReducer was named something else then you'll access it using that key like state.someKeyValue.value

Now we'll be passing the store in the Provider so that the entire application can have access to the store contents.

  1. Open main.jsx and import the Provider and the store.
  2. After importing them, wrap the App in the Provider and pass the Redux store to the Provider as a prop
// src/main.jsx

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

ReactDOM.render(
    <React.StrictMode>
        <Provider store={store}>
            <App />
        </Provider>
    </React.StrictMode>,
    document.getElementById('root')
);

After this step, we'll be able to use the store values in the App.jsx like the following examples

// Using the counter value in App.jsx

import { useSelector } from 'react-redux';

const count = useSelector((state) => state.counter.value);
// Dispatching an action from App.jsx

import { useDispatch } from 'react-redux';
import { increment, decrement } from './features/counter.slice.js';

const dispatch = useDispatch();

handleIncrement = () => {
    dispatch(increment());
}

handleDecrement = () => {
    dispatch(decrement());
}

Adding multiple slices to the store

If in case you want to have more than one slice in the Redux store, it's super easy to do so. Just follow all the above steps to create another slice and then add the slice reducer to the store configuration as shown below.

// src/app/store.js

import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counter.slice';
import userReducer from '../features/counter/user.slice';

export const store = configureStore({
    reducer: {
        counter: counterReducer,
        user: userReducer,
    },
});

You'll be able to access the values by using the user key

// src/App.jsx

const user = useSelector((state) => state.user);

Code

  1. Wanna clone and experiment with the code? Try cloning to local machine
  2. Or experiment online with CodeSandBox ๐Ÿ‘‡

Reference links

  1. Vite docs
  2. Creating a slice w/ createSlice
  3. Configuring the store w/ configureStore
ย