The Redux Toolkit Pattern 
Tags: redux, react, beginners
Published: 2021-09-08 13:15:37

**Redux Toolkit** has been around for a while now. It's still the same state manager we love with a kinda new pattern but still familiar and less overhead a.k.a it's "baggage"!

Since it's 2021, RTL and typescript are perfect together. It would be a crime not to use it together.

## We Begin!
Start with installing Redux and RTL to React.
`npm install @reduxjs/toolkit react-redux`

###The Pattern
As it always is, we start with our `store` file.
Create the file inside `app` folder, which path will look like `src/app/store.ts`. Then lets import `configureStore`
```jsx
import { configureStore } from '@reduxjs/toolkit'

// export the store so we can pass it to our Provider wrapper
export const store = configureStore({
  reducer: {},
})

// Notice that we are exporting inferred typing to be used later for some cool type hintings 
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
``` 

Now, don't forget to wrap your whole app with Redux Provider
```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { store } from './app/store'
import { Provider } from 'react-redux'

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

## Hooks
Before we move on, remember the types we exported from the store earlier? We are going to use that to type charge the hooks for `dispatch` and `selector`

`src/app/hooks.ts`
```jsx
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import { AppDispatch, RootState } from './store'

export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

```

With these you'll get typing on what ever you put into your reducer and initial state when using the Redux hooks

## Slice 
Slice is just where your reducer and action is going to be if your still thinking of classic Redux pattern.

The recommended file structure should follow this file structure pattern `features/counter/counterSlice.ts`
```jsx
import { createSlice, PayloadAction } from '@reduxjs/toolkit'

export interface CounterState {
  value: number
}

const initialState: CounterState = {
  value: 0,
}

export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment: (state) => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. It
      // doesn't actually mutate the state because it uses the Immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes
      state.value += 1
    },
    decrement: (state) => {
      state.value -= 1
    },
    incrementByAmount: (state, action: PayloadAction<number>) => {
      state.value += action.payload
    },
  },
})

// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions

export default counterSlice.reducer
```
 
Then we add the slice to our `store`
`app/store.ts`
```jsx
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'

export default configureStore({
  reducer: {
    counter: counterReducer,
  },
})
```

## Usage
```jsx
import React from 'react'
import { useAppSelector, useAppDispatch } from '../../app/hooks'
import { decrement, increment } from './counterSlice'

export function Counter() {
  const count = useAppSelector((state) => state.counter.value)
  const dispatch = useAppDispatch()

  return (
    <div>
      <div>
        <button
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          Increment
        </button>
        <span>{count}</span>
        <button
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          Decrement
        </button>
      </div>
    </div>
  )
}
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ss9j3ntwoky80nlvz6ua.gif)