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
- Prerequisites
- Bootstrap a React app without any Redux template
- Installing and setting up Redux Toolkit
- Creating a slice
- Configuring the Redux store
- Adding multiple slices to the store
- Code example
- Reference links
Prerequisites
- Familiarity with React JS
- 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 writestate.counter.value
, if thecounterReducer
was named something else then you'll access it using thatkey
likestate.someKeyValue.value
Now we'll be passing the store in the Provider
so that the entire application can have access to the store contents.
- Open
main.jsx
and import theProvider
and thestore
. - After importing them, wrap the
App
in theProvider
and pass the Reduxstore
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
- Wanna clone and experiment with the code? Try cloning to local machine
- Or experiment online with CodeSandBox ๐