What are "Thunk" and `createAsyncThunk` in Redux Toolkit?
Tags: javascript, react, reactnative, redux
Published: 2022-03-01 00:28:34


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

# What Is *Thunk* In Redux?:

*Thunk* is used for fetching data from a API and storing response in Redux states which shortens and increases code clean-up.

# What did you use to fetch data?
First, by using *useEffect* hook and in *componentDidMount* lifecycle, you would have fetched data from an API. What about storing in Redux? You would have used *useDispatch* hook for storing and then using *useSelector* for getting the data.
OK? Now, this operations are assigned to *Thunk* and you don't need to crowd every components in which you use the data you've called an API.

After that, you should check the results for statuses which can be *fulfilled*, *rejected* and *pending* which can be done more easily by using *Thunk*.

And remember this is a quote from Redux Toolkit documentations:
> This abstracts the standard recommended approach for handling async request lifecycles.

*Thus, code is cleaner, more standard and more flexible in writing.*

# Example In Usage
Consider I have a slice called `usersSlice.js`. `createAsyncThunk` will be used and created as shown below. Assume we want to fetch users list from an API:
```javascript
import { createAsyncThunk } from '@reduxjs/toolkit';

export const getUsers = createAsyncThunk(
  'usersSlice/getUsers',
  async () => {
    return await fetch('http://localhost:4000').
      then(res => res.json());
  }
);

const initialState = {
    status: null,
    data: []
}

const usersSlice = createSlice({
    name: 'usersSlice',
    initialState,
    extraReducers: {
      [getUsers.pending] = (state) => {
        state.status = 'Pending';
      },

      [getUsers.fulfilled] = (state, action) => {
        state.status = 'Fulfilled';
        state.data = action.payload;
      },

      [getUsers.rejected] = (state) => {
        state.status = 'Rejected';
      }
    }

export default usersSlice.reducer;
```

First you create a variable called `getUsers` which is assigned to `createAsyncThunk` (notice export keyword before declaring the variable). `createAsyncThunk` has 2 arguments. The first one is a string for specifying the *Thunk* name and the second one is a async function which will return a promise.

Then you create a slice by using `createSlice`. In `extraReducers` (notice `reducers` property is different) you specify 3 probable states of the promise which are `pending`, `fulfilled` and `rejected`. You decide what should Redux do in these 3 different states of the API.

1. *Pending* means API manipulation is being continued.
2. *Fulfilled* means response was got from API.
3. *Rejected* means API call was failure.

After that, you declare the reducer you've created in `configureStore`:
```javascript
import { configureStore } from '@reduxjs/toolkit';
import usersSlice from './slices/usersSlice';

export const store = configureStore({
    reducer: {
        usersSlice,
        ...
    }
});
```

Then, create a component called `UsersListComponent.js` and then, you'll do as this:
```javascript
import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { getUsers } from './store/slices/usersSlice';
...

  const dispatch = useDispatch();
  const usersData = useSelector(state => state.usersSlice.data);
  const usersDataStatus = useSelector(state => state.usersSlice.status);

  useEffect(() => {
    dispatch(getUsers());
  }, []);
```

First you should dispatch the async function you've created by using `createAsyncThunk`. All operations will be done by Redux and BOOM! Everything is ready and you can use `useSelector` hook to get data and use it as you like:
```html
return (
  <>
    {
      usersData.map(userData => (
        <div>
          <span>{userData.id}</span>
          <span>{userData.firstName}</span>
          <span>{userData.lastName}</span>
        </div>
      ))
    }
  </>
);
```

Also you can use `status` state for checking the status of the API:
```html
return (
  <>
    {
      usersDataStatus === 'Pending' ? <span>Pending</span> :
      usersDataStatus === 'Fulfilled' ? <span>Fulfilled</span> :
      usersDataStatus === 'Rejected' ? <span>Rejected</span> : 
      ''
    }

    {
      usersData.map(userData => (
        <div>
          <span>{userData.id}</span>
          <span>{userData.firstName}</span>
          <span>{userData.lastName}</span>
        </div>
      ))
    }
  </>
);
```
Everything works as before but cleaner, more standard and more flexible.
Congratulation! You've been learning how to use *Thunk* and `createAsyncThunk` in Redux Toolkit.