En programmation, le mot thunk fait référence à la partie du code qui effectue un travail différé, comme les fonctions asynchrones en JavaScript.
En soi, un magasin Redux ne gère pas la logique asynchrone. Il sait seulement comment :
Mais attendez, si c'est le cas, comment pouvons-nous appeler des API et mettre à jour l'état en fonction de leurs réponses, ce qui prend généralement du temps ? Comment pouvons-nous gérer cela ?
C'est là qu'interviennent les fonctions thunk.
Une fonction thunk est une fonction créée pour gérer la logique asynchrone, comme appeler une API. Il faut deux arguments dispatch et getState pour distribuer des actions et avoir accès à l'état actuel si nécessaire.
const getAllUsers = () => { return async (dispatch, getState) => { dispatch(fetingAllUsers()); try { const users = await getUsers(); dispatch(userUpdated(users)); } catch (err) { dispatch(logError(err)) } } }
La fonction renvoyée est la fonction thunk et getAllUsers est appelé le créateur de l'action thunk dans cet exemple, et elle serait envoyée comme ceci :
dispatch(getAllUsers())
Un créateur d'action thunk peut être envoyé avec des arguments à utiliser dans la fonction thunk, si nécessaire.
Redux Toolkit fournit l'API createAsyncThunk pour générer facilement des thunks :
import { createAsyncThunk } from '@reduxjs/toolkit'; export const fetchUserById = createAsyncThunk( 'user/fetchUserById', async (userId) => { const user = await someHttpRequest(userId); return user; } );
fetchUserById est la fonction thunk créée ici. createAsyncThunk prend deux arguments :
En plus de vous permettre de créer des fonctions thunk pour les appels d'API, createAsyncThunk distribue automatiquement des actions pour suivre l'état des requêtes d'API :
C'est vraiment utile. Par exemple, nous pouvons afficher un chargeur dans l'interface utilisateur lorsque l'état est en attente et informer l'utilisateur que quelque chose se passe.
Maintenant que nous avons créé le thunk fetchUserById, nous pouvons utiliser le champ extraReducers dans notre userSlice pour gérer les changements de statut d'état :
import { createSlice } from '@reduxjs/toolkit'; const initialState = { user: null, status: 'idle', // 'idle' | 'pending' | 'succeeded' | 'failed' error: null, }; 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;
Et si nous voulons vérifier certaines conditions avant d'appeler l'API ? Par exemple, si le statut est déjà en attente, nous ne voulons pas l’appeler deux fois. Dans ce cas, nous pouvons utiliser le troisième argument accepté par createAsyncThunk pour écrire des conditions.
const getAllUsers = () => { return async (dispatch, getState) => { dispatch(fetingAllUsers()); try { const users = await getUsers(); dispatch(userUpdated(users)); } catch (err) { dispatch(logError(err)) } } }
Pour apprendre à utiliser Typescript avec les fonctions thunk, veuillez lire Type Checking Redux Thunks.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!