No More Redux Boilerblate Hell.(Redux Toolkit)
Tags: redux, beginners, javascript
Published: 2021-10-20 12:05:22

A moment ago @yossefmohamed asked a question on how can he use Redux and Next.js. Well, developers get intimidated by redux because of its boilerplate code before you get it up and running. But they are actually a really cool tool that makes any redux user’s life easy.
Today what I will be showing you guys is [Redux Toolkit](https://redux-toolkit.js.org/) with a simple CRUD example using Next.js. It doesn’t matter if you are already familiar with redux or just got started working with redux, this post is for you.

### What is redux-toolkit?
Redux Toolkit is an opinionated, batteries-included toolset for efficient Redux development. It comes with the most widely used Redux addons out of the box, like Redux Thunk for async logic and Reselect for writing selector functions, so that you can use them right away without having to install them separately.

Enough for the talk, let’s write some code.

First, let’s start by scaffolding a basic Next.js Typescript Project with:

`npx create-next-app redux-toolkit-example --ts`

Your project root would look like this:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ssnq0o1g32tk88r9i7c.png)

## Let’s start building the UI.

Go to *pages/index.js* and replace the default code with this:
```
export default function Home() {
  return (
    <div className="conatiner">
      <div className="list-container">
        <div className="list-header">
          <h1 className="title">
            Lists<span>.</span>
          </h1>
          <div className="input-field">
            <input type="text" className="search" placeholder="Search..." />
            <button className="btn">Search</button>
          </div>
        </div>
        <div className="list-body">
          <div className="list-item">
            <div className="list-item-content">milk</div>
            <button className="list-item-footer">X</button>
          </div>
          <div className="list-item">
            <div className="list-item-content">sugar</div>
            <button className="list-item-footer">X</button>
          </div>
          <div className="list-item">
            <div className="list-item-content">coffee</div>
            <button className="list-item-footer">X</button>
          </div>
          <div className="list-item">
            <div className="list-item-content">eggs</div>
            <button className="list-item-footer">X</button>
          </div>
        </div>
      </div>
    </div>
  );
}


```
Then, go to *styles/global.css* and replace the code with this:

```
html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  background-color: #fafafa;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}

.conatiner {
  max-width: 700px;
  margin: 0 auto;
}

.list-container {
  display: flex;
  justify-self: center;
  align-self: center;
  flex-direction: column;
  width: 500px;
}

.list-header {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.list-header .title {
  font-size: 2rem;
}

.list-header .input-field input {
  margin-right: 1em;
  padding: 8px 10px;
  border-radius: 10px;
  border: #ccc solid 1px;
}

.list-header .input-field button {
  display: inline-block;
  background-color: #78f0f0;
  color: #000;
  border-radius: 10px;
  border: none;
  padding: 8px 10px;
  cursor: pointer;
}

span {
  color: #78f0f0;
}

.list-body {
  width: 100%;
  margin-top: 2em;
}

.list-item {
  display: flex;
  justify-content: space-between;
  margin-bottom: 1em;
}

.list-item button {
  background-color: #78f0f0;
  color: #000;
  border-radius: 50%;
  border: none;
  padding: 8px 10px;
  cursor: pointer;
}


```
Now start the project with yarn or npm depending on the package manager you are using which in my case is npm.

`npm run dev`

This will start the server on *localhost:3000*, then open localhost:3000 in your browser and you will see this printed in the webpage:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/480kq26vvdk7kdib9wat.png)

We are now done building the UI.

## Let's dive into redux-toolkit

Let's start by installing required packages:

`npm i @reduxjs/toolkit react-redux`

When that is done, create a new folder in the root directory call **store**, then create two files *config.js* and *rootReducer.js*  in */store*.

### rootReducer.js

this is the root of all reducers.
insert this code in *rootReducer.js*:

```
import { combineReducers } from "@reduxjs/toolkit";
import { listSlice } from "./ducks/list";

const rootReducer = combineReducers({
  list: listSlice.reducer,
});

export default rootReducer;

```
What happened here is that I imported a `combineReducers()` function from `@reduxjs/toolkit`. The `combineReducers` helper function turns an object whose values are different reducing functions into a single reducing function you can pass to createStore. We will be having a single reducer, so `combineReducers` isn't necessary. But as your app grows more complex, you'll want to split your reducing function into separate functions.
And also import `listSlice` which we have not create yet.

### config.js

*config.js* is a where we configure our redux toolkit.
insert this code in *config.js*:

```
import { configureStore } from "@reduxjs/toolkit";
import rootReducer from "./rootReducer";

const store = configureStore({
  reducer: rootReducer,
});

export type AppDispatch = typeof store.dispatch;
export type AppThunk = ThunkAction<void, RootState, unknown, Action>;

export default store;

```

We now configure the store using the `configureStore` function. `configureStore` is a friendly abstraction over the standard Redux createStore function that adds good defaults to the store setup for a better development experience. this function will automatically configure the redux devtools extension, you can also pass optional configuration to the function. to learn more refer to the [docs](https://redux-toolkit.js.org/api/configureStore).

### Slices

Create a directory call **ducks** with *listSlice.js* file in it.
Paste this in *listSlice.js*:

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

export type listState = {
  list: any[];
};

const initialState: listState = {
  list: ["egg", "milk", "sugar", "coffee"],
};

export const listSlice: any = createSlice({
  name: "list",
  initialState,
  reducers: {
    addList: (state, { payload }) => void state.list.push(payload),
    removeList: (state, { payload }) =>
      void state.list.splice(state.list.findIndex((item) => item === payload)),
  },
  extraReducers: {},
});

export const { addList, removeList } = listSlice.actions;

export const listSelector = (state: any) => state.list;

```

Okay we now create our first slice using the *createSlice* function that performs two actions and we have our initial *list* state with some default items.

### Back to the UI

To use redux in the UI we need to install the [react-redux](https://react-redux.js.org/) library.

`npm i react-redux`

When the installation is done, replace the default code with this in the *_app.js* file.

```
import "../styles/globals.css";

import store from "../store/config";
import { Provider } from "react-redux";

function MyApp({ Component, pageProps }) {
  return (
    <Provider store={store}>
      <Component {...pageProps} />
    </Provider>
  );
}

export default MyApp;


```

Now that we configure redux in our UI let move to *index.tsx* file and Replace it with this updated code:

```
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { addList, listSelector, removeList } from "../store/ducks/list";

export default function Home() {
  const [input, setInput] = useState<string>("");
  const { list } = useSelector(listSelector);
  const dispatch = useDispatch();

  const addItem = () => {
    dispatch(addList(input));
  };
  const removeItem = (value: string) => {
    dispatch(removeList(value));
  };
  return (
    <div className="conatiner">
      <div className="list-container">
        <div className="list-header">
          <h1 className="title">
            Lists<span>.</span>
          </h1>
          <div className="input-field">
            <input
              onChange={(e) => setInput(e.target.value)}
              type="text"
              className="search"
              placeholder="Add"
            />
            <button onClick={addItem} className="btn">
              Add
            </button>
          </div>
        </div>
        <div className="list-body">
          {list &&
            list.map((l: string, index: number) => (
              <div key={index} className="list-item">
                <div className="list-item-content">{l}</div>
                <button
                  onClick={() => removeItem(l)}
                  className="list-item-footer"
                >
                  X
                </button>
              </div>
            ))}
        </div>
      </div>
    </div>
  );
}


```

#Conclusion

Note: this is only the minor basic of redux-toolkit but they are a lot more about this library. 
Thank you for reading my first tutorial on Dev.to, I hope you learn something from this :).