Getting Started With Redux-ToolKit (RTK)
Tags: react, beginners, redux, webdev
Published: 2022-12-31 17:08:57


Managing state is an important aspect of React, For a smaller project, using useState or useReducer is a good way to manage state. But as the application grows complex, we need an efficient way to handle it, React-Redux provides us with global state management and in this article we will explore the concept of state management using [Redux-ToolKit (RTK)](https://redux-toolkit.js.org).

### Table of Content

* [Introduction](#introduction)
* [What is React-Redux?](#what-is-reactredux)
* [Installations](#installation)
* [Setting Up](#setting-up)
  * [ConfigureStore](#configurestore)
  * [Wrap our App with Provider from `React-Redux`](#wrap-our-app-with-provider-from-reactredux)
  * [CreateSlice](#createslice)
      * [todoSlice.js](#todoslicejs)
           * [Add Todo action](#add-todo)
           * [Delete Todo action](#delete-todo)
           * [Update Todo action](#update-todo)
* [Todo App](#todo-app)
    * [Get Initial State](#get-initial-state) 
    * [Add a todo ](#add-a-todo)
    * [Delete a todo ](#delete-a-todo)
    * [Update a todo ](#update-a-todo)


### Introduction

When an action is performed,a state change is expected to happen and trigger the rendering of UI. Managing state  can be done using a `useState` or `useReducer`, It could be complex especially if those components are located in different parts of the application. Sometimes this can be solved by `"lifting state up"` to parent components, but that doesn't always help.

One way to solve this is to extract the shared `state` from the components, and put it into a centralized location outside the component tree where any component can access the `state `or trigger actions, no matter where they are in the `tree`. This is the first of three articles. Other articles are

* [ Making API calls Efficiently with RTK Query]()
* [A guide to using Redux-persist]().

In those articles, I will explain how to use RTK queries to make API calls in efficient ways rather than installing other `packages`, I will also explain redux-persist as an alternative to saving to persist our state or save with details in our App. see you soon.


### What is React-redux

`React-Redux` is a popular JavaScript library that helps developers manage the state of their applications. React-Redux provides a way for a React application to communicate with a central store that holds the state of the application. If you are familiar with react-redux, there are several challenges using it as explained by the documentation  ranging from
 
    1. Configuring a Redux store is too complicated
    2. Installing many Packages
    3. Too much boilerplate code

With those challenges, `RTK` is meant to solve them and provide a way to write efficient ways to set up  and `store` and define `reducers`, 
 
### Installation

For an existing project, run the following code in your terminal

```javascript
npm install @reduxjs/toolkit react-redux

OR

yarn add @reduxjs/toolkit

```

For a new project and this tutorial, we  will create an App with redux template, run the code below, our App name is `redux-tutorial`

```javascript
npx create-react-app redux-tutorial --template redux

```
After the installation, run

```javascript

cd redux-tutorial

code .

npm start

```

Your `package.json` file should like this, `redux-toolkit` and `react-redux` will be installed.

![redux-tool-kit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/brkofot6t53s0pgx7e7o.png)

### Setting up

In this Tutorial, we will be building a simple `Todo` list to illustrate our work. We need to basically go through three basic step as listed below

* [Configure Store](#configurestore)
* [Wrap our App with Provider from react-redux](#wrap-our-app-with-provider-from-reactredux) *
* [Create Slices](#createslice)
* [Dispatch our action and get state](#todo-app)

 *_Only necessary if you are using an existing App_

In our `features` folder, a subfolder of `src`, create another folder called `todo` where all our configurations will be. For those that installed with `redux template`, all configurations have been done. For existing project, create a folder `store` and add `index.js`. 

#### ConfigureStore

The `configureStore` function is used to create a Redux store that holds the complete state tree of our App. Configure store accepts `reducers` as the required parameters, others parameters that can be included are

* Thunk middleware
* Redux DevTools
* PreloadedState​
* Enhancers​

Lets create our `store`by importing the following

`src/app/store.js ` OR `./store`

```javascript

import { configureStore } from '@reduxjs/toolkit';
import todoReducer from  "features/todo/todoSlice.js"
export const store = configureStore({
  reducer: {
    todos: todoReducer,
  },
});

```
Here, we import our `todoReducer` (which will be created soon). the import was done using absolute path. Read more about absolute path in my article [here](https://dev.to/isiakaabd/configuring-absolute-path-in-react-projects-4h9o). We can have multiple `reducers` combined together.  later on, we will use `todos` as the key to access our state.

### Wrap our App with Provider from react-redux

```javascript

import React from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import { store } from "./app/store";
import App from "./App";

const container = document.getElementById("root");
const root = createRoot(container);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

```

### CreateSlice

This helps us to write reducers without the need to spread our state. `Redux Toolkit` allows us to write "mutating" logic in reducers. It doesn't actually mutate the state because it uses the [Immer library](https://redux-toolkit.js.org/usage/immer-reducers), It also automatically generates action creator functions for each reducer. It literarily saves us with writing our `actions` type logic repetitively.

In `features` folder, create another folder `todo` and add `todoSlice.js` where we write our `todoSlice`

#### todoSlice.js

```javascript

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

const initialState = {
  todoList: [],
};

export const todoSlice = createSlice({
  name: "todos",
  initialState,

  reducers: {},
});
const { actions, reducer } = todoSlice;

export const {} = actions;

export default reducer;

```
This is a `boilerplate` for writing our slices, in our `createSlice` function, we passed in our name, the initial State and our reducers.

##### Actions

let's write our first action,  `addTodo` add a new todo to the list and we create it  in   `reducers` object as below

###### Add Todo

```javascript

addTodo: (state, action) => {

state.todoList.push(action.payload);

}

```
Here we are using the `push` method to add new todo to our list. `action.payload` is the `todo` that will be added to `todoList`.


###### Delete Todo
To be able to delete from the list, we use the `index` to select a particular `todo` and use the array method of `splice`. here is the code:

```javascript
 deleteTodo: (state, action) => {
      state.todos.splice(state.todos.indexOf(action.payload), 1);

},

```
###### Update Todo

```javascript

 updateTodo: (state, action) => {
      const todo = state.todoList.findIndex(action.payload.id);
      state.todos[todo] = action.payload;
 }

```

We can export all our `actions` and our final code like this

```javascript

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

const initialState = {
  todoList: [],
};

export const todoSlice = createSlice({
  name: "todos",
  initialState,

  reducers: {
    addTodo: (state, action) => {
      state.todoList.push(action.payload);
    },
    deleteTodo: (state, action) => {
      
   state.todoList.splice(state.todoList.indexOf(action.payload), 1);
    },
    updateTodo: (state, action) => {
      const todo = state.todoList.findIndex(action.payload.id);
      state.todoList[todo] = action.payload;
    },
  },
});

const { actions, reducer } = todoSlice;

export const { addTodo } = actions;

export default reducer;

```

With this we concluded writing on `redux` logic, last thing we need to do is to import it in our App.


### useDispatch and useSelector

The two hooks work to get `set` and `get` data from our store. if we need to modify the state, `useDispatch` will be used to dispatch an `action` while if we need to access our state, `useSelector` will be used.

### Todo App

For this, we created our `Todo component` in the root of our `src` folder, our folder structure should look like this



![folder_structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yy4xzmt0hhq5doezwjz5.png)
 

We create a simple UI and you can have access to the code in the linked [repository](https://github.com/isiakaabd/react-redux-tutorial.git).. Here is the code in our `Todo.js`  file

```javascript

import { useState } from "react";
import {  useSelector } from "react-redux";

const Todo = () => {
  const [todo, setTodo] = useState("");
  const state = useSelector((state) => state.todos.todoList);

  return (
      <div className="todo">
      <h3>Simple Todo App</h3>
   <div className="input__container">
   
      <input
        type="text"
        value={todo}
        onChange={(e) => setTodo(e.target.value)}
      />

      <button>Add Todo</button>
    </div>
     <ol>
        {state.length > 0 &&
          state.map((todo, index) => {
            return (
              <li key={index}>
                <h6>{todo} </h6>

                <button name="edit">Edit</button>

                <button name="delete">
                  Delete
                </button>
              </li>
            );
          })}
      </ol>
    </div>
  );
};

export default Todo;


```
The first thing we do here is to get the current state of our `todoList` using `useSelector` hook, we have

##### Get Initial State

```javascript

const state = useSelector((state) => state.todos.todoList);

```
`todos` here refer to the name of the `reducer` we used when configuring our store. So we have access to our `todoList` array which contains our `initialState` and if we log it to `console`, we have

![console.image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxuwogyrtzps7kmpcal9.png)

##### Add a Todo   

To add to the list, we need to `dispatch` our `addTodo` action as shown below. we will use `useDispatch hook`. 
* first we call the useDispatch and assigned it to dispatch variable.

```javascript
  const dispatch = useDispatch();
```
* We dispatch our action when we clicked the button, with our `todo` as a paramater as shown below. we checked if there's `todo` before we dispatch our action and clear our input field afterwards

```javascript

     <button onClick={() => {
                 if (!input) return;
                 dispatch(addTodo(input));
                 setInput("");
                 }}
     >
     Add Todo
     </button>

```
on the click of Add Todo `button`, we have something similar to this


![Added todolist](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2cp0l6ijomae0vmz9cdh.png)

##### Delete a todo 

Similar to what we did for `addTodo`, we will pass the `index` a todo and dispatch our `deleteTodo` action

```javascript

import { addTodo, deleteTodo } from "features/todo/todoSlice";

```
In our `edit button`, we add the code to set our todo to the input value, here is how our button code looks like

```javascript
 <button name="delete" onClick={()=>dispatch(deleteTodo(index))}>
 Delete
 </button>

```
##### Update a todo 

Here , we need to select a particular todo item and make update to it, full details to the implementation is available in the [repo](https://github.com/isiakaabd/react-redux-tutorial.git).

Thank you for reading. Please leave a comment if you have any question or clarification and I hope you've learned something new from this post. Want to stay up to date with regular content regarding JavaScript, React and React-Native? Follow me ❤️ on [LinkedIn](https://linkedin.com/in/isiakaabd).