Basics of Redux Toolkit
Published: 2022-01-05 16:29:57

#What is Redux ?
Redux is an open-source JavaScript library for managing application state. It is most commonly used with libraries such as React or Angular for building user interfaces

#What is Redux Toolkit ?
Redux Toolkit (RTK), previously known as Redux Starter Kit, provides some options to configure the global store and create both actions and reducers in a more streamlined manner. Redux toolkit includes all the tools, you want for a Redux application.

By using this, you can write all the code you need for your Redux store in a single file, including actions and reducers. Using this you can make your code more readable.

#Why Redux Toolkit 🤷‍♂️?
Redux Toolkit is mainly created to solve the three major issues with Redux:
* **Configuring a Redux store is too complicated:** Redux Toolkit offers configureStore function to simplify configuration.
* **Need to add lots of packages:** Redux Toolkit reduces the need to add multiple packages to build large scale application
* **Too much boilerplate code:** Redux requires too much boilerplate code which makes it cumbersome to write efficient and clean code. Redux Toolkit helps to reduce boilerplate code.

#Redux Toolkit comes pre-bundled with the below features:
* immer.js => a library/tool to handle immutability in stores.
* redux => For state management
* redux-thunk =>For async tasks
* reselect => For selecting a slice out of global store
* automatic support for Redux Dev-tools Extension

#Start with Redux Toolkit
You will need to include Redux as well as the react-redux binding package for it to work properly with React. You’ll also need the Redux Toolkit itself.

```
npm i redux react-redux @reduxjs/toolkit
```
Usually, you would also need the Redux DevTools extensions in order to debug your store mutations correctly; but since you’re using RTK, those are already included.

#Important Terms Used In Redux Toolkit 
1.Store
2.createSlice
3.name
4.initialState
5.reducers
6.extraReducers
7.createReducer
8.createAction
9.createAsyncThunk
10.createEntityAdapter
11.createSelector

#Creating store
In traditional Redux, you had to call createStore using the main reducer as a parameter. The way to do it with RTK is to call **configureStore**, which allows you to do the same.
```
import { configureStore } from "@reduxjs/toolkit";
import { combineReducers } from "redux";
import logger from 'redux-logger'

import usersReducer from "./slices/userSlice";
import postsReducer from "./slices/postSlice";

const rootReducer = combineReducers({
  users: usersReducer,
  posts: postsReducer
});

const preloadedState = {
  postsData: [
    {
      text: 'JavaScript Centric',
      completed: true,
    },
    {
      text: 'Lucky Gamer',
      completed: false,
    },
  ]
}

const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
  devTools: process.env.NODE_ENV !== "production",
  preloadedState,
  enhancers: [reduxBatch],
});

export default store;
```
Here configureStore has five parameters(reducer, middleware, devtools, preloadedState, enhancers).

**reducer** is a single function, it will be directly used as the root reducer for the store. If it is an object of slice reducers, like {users : usersReducer, posts : postsReducer}, **configureStore** will automatically create the root reducer by passing this object to the Redux **combineReducers** utility.

**middleware** is an optional array of Redux middleware functions. If this option is provided, it should contain all the middleware functions you want added to the store. configureStore will automatically pass those to **applyMiddleware**.

**devTools** has default boolean value of true and will be used to indicate whether configureStore should automatically enable support for the Redux DevTools browser extension. If it is an object, then the DevTools Extension will be enabled, and the options object will be passed to composeWithDevtools(). 

**preloadedState** is an optional initial state value to be passed to the Redux createStore function.

**enhancers** is an optional array of Redux store enhancers, or a callback function to customize the array of enhancers. Example: enhancers: [offline] will result in a final setup of [applyMiddleware, offline, devToolsExtension].

#createSlice:
createSlice is a higher order function that accepts an **initial state**, an **Object full of reducer functions**, and a **slice name**, and returns a single reducer along with the action creators for that reducer. (Automatically generates action creators and action types that correspond to the reducers and state).

We can Import the createSlice method from the redux-toolkit library.

```
import { createSlice } from '@reduxjs/toolkit'
const initialState: {
        users: []
    }

const userSlice = createSlice({
    name: 'user',
    initialState,
    reducers: {
        getUsers: (state, action) => {
            state.users = action.payload;
        }

    },
});

export const { getUsers } = userSlice.actions;
export default userSlice.reducer;
```

createSlice looks at all the functions that are defined in the reducers field and for every case generates an action creator that uses the name of the reducer as the action type itself.

**initialState** value for this slice of state.

**name** a string name for this slice of state. Generated action type constants will use this as a prefix.

**reducers** is an object containing Redux "case reducer" functions. The keys in the object will be used to generate string action type constants, and these will show up in the Redux DevTools Extension when they are dispatched. 


#createAction
is a simple helper function that accepts an action type (string) and returns an action creator. The usual way to define an action in Redux is to separately declare an action type constant and an action creator function for constructing actions of that type.

#createReducer 
is a function that accepts an object where the keys are the action type and the values are the reducer.

```
import { createAction, createReducer } from '@reduxjs/toolkit'

const increment = createAction('counter/increment')
const decrement = createAction('counter/decrement')

const counterReducer = createReducer(0, (builder) => {
  builder.addCase(increment, (state, action) => state + action.payload)
  builder.addCase(decrement, (state, action) => state - action.payload)
})
```
It supports two different forms of defining case reducers to handle actions: a **"builder callback"** notation and a **"map object"** notation. Both are equivalent, but the "builder callback" notation is preferred.

That builder provides **addCase, addMatcher and addDefaultCase** functions that may be called to define what actions this reducer will handle.

A callback that receives a builder object to define case reducers via calls to
`builder.addCase(actionCreatorOrType, reducer).`

All calls to builder.addCase must come before any calls to builder.addMatcher or builder.addDefaultCase.