Redux Toolkit: Creating Thunk Functions
December 22, 2024

Redux Toolkit: Creating Thunk Functions


What is a Thunk?

In programming, the word Blow Refers to the portion of code that performs deferred work, such as an asynchronous function in JavaScript.

Redux storage itself does not handle asynchronous logic. It only knows how to:

  1. Schedule actions synchronously.
  2. Update status via reducer.
  3. Notify the UI about state changes.

But wait, if that’s the case, how do we call the API and update the status based on their response, which usually takes time? How should we deal with this?

This is where the thunk function comes into play.


What is the Thunk function?

Thunk functions are functions built to handle non-synchronous logic (such as calling APIs). It takes two parameters dispatch and getState Schedule operations and access current state when needed.

const getAllUsers = () =>  'failed'
  error: null,

Enter full screen mode

Exit full screen mode

The function returned is a thunk function and getAllUsers Called the thunk action creator in this case, it will be dispatched like this:

dispatch(getAllUsers())
Enter full screen mode

Exit full screen mode

If needed, the thunk operation creator can be scheduled using the parameters used in the thunk function.


Create a thunk using the following command createAsyncThunk

The Redux toolkit provides createAsyncThunk API to easily generate thunks:

import 
        state.status = 'failed';
        state.error = action.error.message  from '@reduxjs/toolkit';

export const fetchUserById = createAsyncThunk(
  'user/fetchUserById',
  async (userId) => 
);
Enter full screen mode

Exit full screen mode

fetchUserById is the thunk function created here. createAsyncThunk There are two parameters:

  • The first argument is a string prefix for the type of operation to be produced (e.g. user/fetchUserById/pending, user/fetchUserById/fulfilledor user/fetchUserById/rejected).
  • The second parameter is the “payload creator” function. It should return a Promise with the required data or an error.


Why use createAsyncThunk?

In addition to letting you create thunk functions for API calls, createAsyncThunk Automatically schedule operations to track the status of API requests:

  • pending: The request is in progress.
  • fulfilled: The request was successful.
  • rejected: The request failed.

This is really useful. For example, we can show the loader in the UI when the status is pending and let users know something is going on.


Using thunks in slices

Now we have created fetchUserById thunk, we can use extraReducers our areas userSlice Handling status changes:

import 
  user: null,
  status: 'idle', // 'idle'  from '@reduxjs/toolkit';

const initialState =  'Something went wrong.';
      ;

export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    usernameUpdated: (state, action) => {
      state.user.username = action.payload;
    },
    emailUpdated: (state, action) => {
      state.user.email = action.payload;
    },
    userDataCleared: (state) => {
      state.user = null;
      state.status = 'idle';
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchUserById.pending, (state) => {
        state.status = 'pending';
      })
      .addCase(fetchUserById.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.user = action.payload;
      })
      .addCase(fetchUserById.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message || 'Something went wrong.';
      });
  },
});

export const { usernameUpdated, emailUpdated, userDataCleared } = userSlice.actions;

// Selector for the status to use in the application's components
export const selectStatus = (state) => state.user.status;
Enter full screen mode

Exit full screen mode



createAsyncThunk situation

What if we want to check some conditions before calling the API? For example, we don’t want to call it twice if the state is already pending. In this case we can use the third parameter createAsyncThunk Accept the writing conditions.

export const fetchUserById = createAsyncThunk(
  "user/fetchUserById",
  async (userId) => {
    const response = await someHttpRequest(userId);
    return response;
  },
  {
    condition(_, { getState }) {
      const status = selectStatus(getState());
      if (status !== "idle") {
        return false;
      }
    },
  }
);
Enter full screen mode

Exit full screen mode

To learn how to use Typescript with thunk functions, read Type checking Redux thunk.

2024-12-22 17:59:13

Leave a Reply

Your email address will not be published. Required fields are marked *