Search for a command to run...

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
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.
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
featurefolder 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.
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.
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
reducerfield 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 thecounterReducerwas named something else then you'll access it using thatkeylikestate.someKeyValue.value
Now we'll be passing the store in the Provider so that the entire application can have access to the store contents.
main.jsx and import the Provider and the store. 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());
}
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);