Migrating from Redux Thunk to Redux Toolkit
Demonstrate the process of migrating a pre-existing Redux thunk middleware to the Redux Toolkit's createAsyncThunk for better Redux v5.0.0 compatibility.
// Old Redux Thunk action creator
export const fetchUserData = (userId) => {
return (dispatch) => {
dispatch({ type: 'USER_FETCH_REQUESTED' });
return fetch(`/api/users/${userId}`)
.then(response => response.json())
.then(data => dispatch({ type: 'USER_FETCH_SUCCEEDED', payload: data }))
.catch(error => dispatch({ type: 'USER_FETCH_FAILED', payload: error }));
};
}
This is an example of a traditional Redux thunk action creator. It dispatches actions based on asynchronous API call results.
// Slice.js using Redux Toolkit's createSlice and createAsyncThunk
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// New Redux Toolkit createAsyncThunk
export const fetchUserData = createAsyncThunk(
'user/fetchUserData',
async (userId, thunkAPI) => {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
return thunkAPI.rejectWithValue(await response.json());
}
const data = await response.json();
return data;
}
);
// Slice to handle the action
export const userSlice = createSlice({
name: 'user',
initialState: {},
reducers: {},
extraReducers: {
[fetchUserData.pending]: (state) => {
// Handle pending state
},
[fetchUserData.fulfilled]: (state, action) => {
// Handle fulfilled state and update the state with payload
},
[fetchUserData.rejected]: (state, action) => {
// Handle rejected state
},
},
});
This code snippet replaces the traditional Redux thunk action creator with Redux Toolkit's createAsyncThunk, which automatically handles dispatching actions for pending, fulfilled, and rejected states of the async operation. A slice is also defined to handle the action states using createSlice.
// store.js setup for Redux Toolkit
import { configureStore } from '@reduxjs/toolkit';
import { userSlice } from './userSlice';
// Configure the store with Redux Toolkit, automatically setting up the middleware
export const store = configureStore({
reducer: {
user: userSlice.reducer,
},
});
This is the new Redux store configuration using Redux Toolkit's configureStore. It sets up the middleware automatically and includes the user slice.reducer for the user's state.
<!-- index.html, simple setup for Redux with Redux Toolkit -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Redux Toolkit Migration</title>
</head>
<body>
<div id="app"></div>
<script src="path_to_your_bundled_javascript_file.js"></script>
</body>
</html>
This is a simple HTML to setup the Redux application. Your bundled JavaScript file should be included at the end of the body tag.
/* styles.css, basic styling example for the Redux application, */
#app {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
A simple CSS snippet to style the #app container element, centering its content both horizontally and vertically.