Redux Toolkit
Tags: beginners, reduxtoolkit, react, webdev
Published: 2022-11-16 15:30:12

So according to the official documentation of **redux** now **redux toolkit** is the only way to write **redux** logic ,as a matter of fact it was introduced due to the following three reasons :

- Configuring **redux** store is too complicated
- A lot of packages needed to be added to make **redux** logic work
- Also it requires too much boilerplate code

Let’s work with an application which make use of **redux toolkit** to manage the state of application .

So talking about the project it is a simple shopping cart in which we can add some products to the cart , we can remove products , we can increase the amount of products too and all this functionality will be achieved via redux-toolkit.  

Firstly install **redux-toolkit** in your react application with the following command

```jsx
npm install @reduxjs/toolkit
```

As we used to create store , exactly same way we are going to create store in our application

```jsx
  import { configureStore } from "@reduxjs/toolkit";
	export const store=configureStore({
    reducer:{
       
    }
})
```

`configureStore` accept an argument of reducer key which accepts all the slice reducers of the application and it combine all the slice reducer to form the root reducer , basically reducer is an object of the slice reducer .

Now if you don’t know what slice reducer is don’t worry by the end of this blog you will get familiar with all the jargon .

Once store is created now we need to make store available to the whole application  so that any component can access the state of the application and how we are going to achieve this for that let's move to the main.jsx of our application where we have to wrap our App inside the `provider` which can be imported from the **react-redux** and we need to pass store as props in Provider .

basically `provider` is used to make store available to the nested components therefore it is passed at the top level this is the reason why we have nested our App inside Provider .

```jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { Provider } from 'react-redux'
import App from './App'
import './index.css'
import { store } from './store'

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

So our setup is done , now let’s learn how to create state with `createSlice` API , think of it as one of the feature of your application , in our project we are managing the products of cart therefore slice logic revolve around products of cart only .

`createSlice` object accepts an name key , initialstate value and  object of reducer function , also it helps to manage **redux** related logic for a given slice in single file .

Therefore let’s create a feature folder under which create a bag folder and finally under the bag folder create a bag file 

```jsx
import { createSlice } from "@reduxjs/toolkit"
import bagItems from "../../data/data";
const initialState={
    amount:0,
    total:0,
    bagitem:bagItems,
    totalcart:[]
}
const  bagSlice=createSlice({
    name:'bag',
    initialState,
})
export default bagSlice.reducer;
```

As you can see in above file a slice is created with the name **bag** and a **initial state** is passed with **amount** equal to zero which signify the amount of products in cart , **total** will be used to calculate the total price of cart , **totalcart** is kept empty as it will used for storing cart items and **bagItems** contains the product in our shopping app for which I have created the data which is imported from the data file . In order to access the data you can visit to the github repository of this project link for which is mentioned below .   

One thing to note here is that **bagSlice** is an object which have action , reducer and some other properties from which we have exported reducer as shown in above file .

I have log the **bagSlice** in order to show you the object which clearly shows that **bagSlice** contain object of actions , reducer etc .

 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqvvmqle8s6fhu125oou.png)

Remember in beginning we created a store in our application which take an argument of reducer object therefore in order to make this bag slice available to our whole application we need to export the slice reducer to our store .

```jsx
import { configureStore } from "@reduxjs/toolkit";
import bagReducer from "./features/bag/bag.jsx"
export const store=configureStore({
    reducer:{
        bag:bagReducer
    }
})
```

therefore in the store file we can see that we have passed the **bagReducer** imported from bag Slice to a key named bag .

Likewise if there are any other slice in your application needs to be added to the reducer object. 

Now let’s move to our home page where we will just show the products name , image and their price and a button used to add products to cart .

Also we can look at the state in our **redux devtool** in console as shown below


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ehhjjq0xote1dsppto96.png)

Now let’s learn how to access state from slice  in our components for this purpose we are going to import `use Selector` in our home page, it is used to access the state from store.

```jsx
import React from 'react'
import { useSelector } from 'react-redux'
const Home = () => {
  const { bagitem } = useSelector((store) => store.bag)
  console.log(bagitem);
  return (
    <div className='home'>
      <div className="mid">
{
        bagitem.map((item)=>{
          return <Item key={item.id} {...item}/>
        })
      }

      </div>
      <div className='tact'>

      <button ><Link to="/bag">
      Go to Cart
      </Link>
      </button>
      </div>
      </div>
    </div>
  )
}
export default Home
```

As for now currently we have only one slice therefore in the above code we can see that we are accessing the bag slice from store and we are destructuring bag item from this .In order to check whether we are getting the data or not I have log the value of **bagitem** let’s check

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8erkhsh2zw5ru5zutqgz.png)

therefore it can be clearly observed that we are able to access the value and our code is working fine up till now.

Our home page kinda look like this as shown below , in this tutorial we are going to keep our focus on the **redux-toolkit** only therefore if you want to check the code part of the user interface I have added the github link of this repository at the end .


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sdwex8or0d4s56wb5edf.png)

So far we have covered how to create state and how to access the state value from store now let’s take one step ahead and create reducer function in our slice , reducer function contain the logic and calculation needed to be performed on state.

As you can see we have **add to cart** button in our app so when user click on this we need to add that product in our cart and to achieve this we need to create a reducer function let ‘s create it

```jsx
import { createSlice } from "@reduxjs/toolkit"
import bagItems from "../../data/data";
const initialState={
    amount:0,
    total:0,
    bagitem:bagItems,
    totalcart:[]
}
const  bagSlice=createSlice({
    name:'bag',
    initialState,
    reducers:{
      addtocart:(state,{payload})=>{
        const bagItem=state.bagitem.filter((item)=>item.id===payload.id);
        state.totalcart.push(bagItem[0]);
      }  
    }
})
export const {addtocart}=bagSlice.actions
export default bagSlice.reducer;
```

> One thing to note here is **redux toolkit** automatically uses **immer library** therefore we do not need to return new state in our reducer function we can make changes directly to the state
> 

`addtocart` is a reducer function i.e it takes previous state and action as an argument and  return a new state with applied changes here I have destuctured the payload from action .

In the above code we can see that I have created a `addtocart `function so what is happening in this function is that if a user click on the button add to cart that product is added to the **totalcart** which was initially kept to be empty .

Now we need to export this function in order to make use of it in components and we can export it by destructuring it from actions property of bagSlice.

Now we need to make use of this function in our component for this purpose let ‘s make use of `usedispatch` it give us store dispatch method which basically affect the state of store .

```jsx
import React from 'react'
import { useDispatch } from 'react-redux'
import "../App.css"
import { addtocart } from '../features/bag/bag';
const Item = ({ title, img, price, id }) => {
  const dispatch = useDispatch();
  return (
    <table className="item">
     <tr>
        <td>
          <img src={img} style={{ height: "50px", width: "50px" }} alt="" />
        </td>
        <td>
          <p>{title}</p>
        </td>
        <td>
          <p className='price'>${price}</p>
        </td>
        <td>
          <button className='buts' onClick={() => dispatch(addtocart({ id }))}>Add To Cart</button>
        </td>
      </tr>
    </table>
  )
}

export default Item
```

dispatch takes the reducer function as an argument and it call the reducer function which finally make changes in the state .

In the above code we can see that we are importing `usedispatch` from react-redux and we are making use of it in the button to access `addtocart` function from state also we are passing the id as argument in function `addtocart` because on the basis of this only selected product will be added to total cart .

Suppose if user add the first product in **totalcart** and then let’s check the state in **redux devtool** →the product can be viewed in **totalcart**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w1x04qizc02s6ysvwvhu.png)

 Also we can view the difference in our **redux devtool**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxfvsmaiqeftd2ko5bz3.png)

The highlight part shows that earlier the **totalcart** was empty now it contain a product .

Once done with the home page now let’s move to our cart page where we can explore other reducer function .

 Our cart page look like this 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igapf81b3vz5fzphms1x.png)
Things to notice in cart page are that we can increase and decrease the amount of product , with the increase in amount of product the total price of cart is increasing with it which can be seen at bottom of cart page plus total amount of product is also increasing which can be seen at the navbar and we also have a remove item button to delete item from cart .

Now we need to create reducer function for all this functionality in our slice

```jsx
import { createSlice } from "@reduxjs/toolkit"
import bagItems from "../../data/data";

const initialState={
    amount:0,
    total:0,
    bagitem:bagItems,
    totalcart:[]
}

const  bagSlice=createSlice({
    name:'bag',
    initialState,
    reducers:{
      addtocart:(state,{payload})=>{
        const bagItem=state.bagitem.filter((item)=>item.id===payload.id);
        state.totalcart.push(bagItem[0]);
      } ,
      removeItem:(state,{payload})=>{
       state.totalcart=state.totalcart.filter((item)=>item.id!==payload.id);
      } ,
      increaseitem:(state,{payload})=>{
        const cartitem=state.totalcart.find((item)=>item.id===payload.id)
        cartitem.amount=cartitem.amount+1;
      },
      decreaseitem:(state,{payload})=>{
        const cartitem=state.totalcart.find((item)=>item.id===payload.id)
        cartitem.amount=cartitem.amount-1;
      },
      totalamount:(state)=>{
        let amount=0;
        let total=0;
        state.totalcart.forEach((item)=>{
          amount+=item.amount;
          total+=item.amount*item.price;
        })
        state.amount=amount;
        state.total=total;
      }
    }
})
export const {addtocart,removeItem,increaseitem,decreaseitem,totalamount}=bagSlice.actions
export default bagSlice.reducer;
```
- **removeitem**→ it is a simple function where we are just deleting a element from array .
- **increaseitem**→ In this function we are increasing the amount of product
- **decreaseitem** → In this function we are decreasing the amount of product
- **totalamount** → In this function we are traversing through the whole array and we are calculating the total amount and total price of cart .

 
One thing to notice here is we are accessing totatlcart from state not bagitem because we are making changes in the cart  .

Now we just need to dispatch these function in our cart as shown below 

Parent component is the bag page

```jsx

import React from 'react'
import { useSelector } from 'react-redux'
import Cart from '../components/Cart';
const Bag = () => {
  const { totalcart, total } = useSelector((state) => state.bag);
  console.log(totalcart)
  return (
    <div>
      { totalcart ? (totalcart.map((item) => {
          return <Cart key={item.id} {...item} />
        })) : (
          null   )   }
      <br />
      <hr />
      <div className='total'>
        <p>
          total
        </p>
        <p>${total}</p>
      </div>
    </div>
  )
}
export default Bag

```

the child component cart is shown below

```jsx
import React from 'react'
import { useDispatch } from 'react-redux'
import { decreaseitem, increaseitem, removeItem } from '../features/bag/bag';
const Cart = ({ title, img, price, id, amount }) => {
  const dispatch = useDispatch();
  return (
    <table className="item">    
      <tr>
        <td>
          <img src={img} style={{ height: "50px", width: "50px" }} alt="" />
        </td>
       <td>
          <p>{title}</p>
        </td>     
        <td>
          <p className='price'>${price}</p>
        </td>
        <td>
          <button onClick={() => dispatch(increaseitem({ id }))}>+</button>
          {amount}
          <button onClick={() => {
            if (amount === 1) {
              dispatch(removeItem({ id }));}
            dispatch(decreaseitem({ id }))
          }} >-</button>
        </td>
        <td>
          <button onClick={() => dispatch(removeItem({ id }))}>Remove Item</button>
        </td>
      </tr>
    </table>
  )
}

export default Cart
```

Repository Link 
https://github.com/2devyank/Redux-toolkit
Star this repository If you find it useful