Je pense, en utilisant useEffect
n'est pas un moyen intuitif.
J'ai créé un wrapper pour cela. Dans ce hook personnalisé, vous pouvez transmettre votre callback à setState
au lieu du paramètre useState
paramètre.
Je viens de créer la version Typescript. Donc si vous avez besoin de l'utiliser en Javascript, il suffit d'enlever certaines notations de type du code.
Utilisation
const [state, setState] = useStateCallback(1);
setState(2, (n) => {
console.log(n) // 2
});
Déclaration
import { SetStateAction, useCallback, useEffect, useRef, useState } from 'react';
type Callback<T> = (value?: T) => void;
type DispatchWithCallback<T> = (value: T, callback?: Callback<T>) => void;
function useStateCallback<T>(initialState: T | (() => T)): [T, DispatchWithCallback<SetStateAction<T>>] {
const [state, _setState] = useState(initialState);
const callbackRef = useRef<Callback<T>>();
const isFirstCallbackCall = useRef<boolean>(true);
const setState = useCallback((setStateAction: SetStateAction<T>, callback?: Callback<T>): void => {
callbackRef.current = callback;
_setState(setStateAction);
}, []);
useEffect(() => {
if (isFirstCallbackCall.current) {
isFirstCallbackCall.current = false;
return;
}
callbackRef.current?.(state);
}, [state]);
return [state, setState];
}
export default useStateCallback;
Drawback
Si la fonction flèche passée fait référence à une fonction externe variable, alors elle capturera la valeur actuelle et non une valeur après la mise à jour de l'état. Dans l'exemple d'utilisation ci-dessus, console.log(état) imprimera 1 et non 2.
2 votes
Dans la classe component, j'ai utilisé async et await pour obtenir le même résultat que ce que vous avez fait pour ajouter un callback dans setState. Malheureusement, cela ne fonctionne pas dans le hook. Même si j'ai ajouté async et await, react n'attend pas la mise à jour de l'état. Peut-être que useEffect est le seul moyen de le faire.
2 votes
@Zhao, vous n'avez pas encore marqué la bonne réponse. Pouvez-vous gentiment nous accorder quelques secondes