Je suggère de regarder la réponse de Dan Abramov (l'un des principaux responsables de React) ici :
Je pense que vous rendez les choses plus compliquées que nécessaire.
function Example() {
const [data, dataSet] = useState<any>(null)
useEffect(() => {
async function fetchMyAPI() {
let response = await fetch('api/data')
response = await response.json()
dataSet(response)
}
fetchMyAPI()
}, [])
return <div>{JSON.stringify(data)}</div>
}
À plus long terme, nous découragerons ce modèle car il encourage les conditions de course. Tels que - tout pourrait arriver entre le début et la fin de votre appel, et vous auriez pu obtenir de nouveaux accessoires. Au lieu de cela, nous vous recommandons Suspense pour la récupération de données qui ressemblera davantage à
const response = MyAPIResource.read();
et aucun effet. Mais en attendant, vous pouvez déplacer le contenu asynchrone vers une fonction distincte et l'appeler.
Vous pouvez en savoir plus sur le suspense expérimental ici .
Si vous souhaitez utiliser des fonctions à l'extérieur avec eslint.
function OutsideUsageExample() {
const [data, dataSet] = useState<any>(null)
const fetchMyAPI = useCallback(async () => {
let response = await fetch('api/data')
response = await response.json()
dataSet(response)
}, [])
useEffect(() => {
fetchMyAPI()
}, [fetchMyAPI])
return (
<div>
<div>data: {JSON.stringify(data)}</div>
<div>
<button onClick={fetchMyAPI}>manual fetch</button>
</div>
</div>
)
}
Avec useCallback, useCallback . Bac à sable .
import React, { useState, useEffect, useCallback } from "react";
export default function App() {
const [counter, setCounter] = useState(1);
// if counter is changed, than fn will be updated with new counter value
const fn = useCallback(() => {
setCounter(counter + 1);
}, [counter]);
// if counter is changed, than fn will not be updated and counter will be always 1 inside fn
/*const fnBad = useCallback(() => {
setCounter(counter + 1);
}, []);*/
// if fn or counter is changed, than useEffect will rerun
useEffect(() => {
if (!(counter % 2)) return; // this will stop the loop if counter is not even
fn();
}, [fn, counter]);
// this will be infinite loop because fn is always changing with new counter value
/*useEffect(() => {
fn();
}, [fn]);*/
return (
<div>
<div>Counter is {counter}</div>
<button onClick={fn}>add +1 count</button>
</div>
);
}
useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, [])
eslint
me demande de fairefetchMyAPI()
comme dépendance deuseEffect
Lorsque vous utilisez une fonction asynchrone comme
il renvoie une promesse et
useEffect
n'attend pas que la fonction de rappel renvoie Promise, mais s'attend plutôt à ce que rien ne soit retourné ou qu'une fonction soit retournée.Pour contourner l'avertissement, vous pouvez utiliser une fonction asynchrone à invocation automatique.
ou pour le rendre plus propre, vous pouvez définir une fonction puis l'appeler
la deuxième solution facilitera la lecture et vous aidera à écrire du code pour annuler les demandes précédentes si une nouvelle est déclenchée ou à enregistrer la dernière réponse à la demande dans l'état
Codes de travail et boîte
la source
useEffect
vous pouvez renvoyer une fonction pour faire le nettoyage, comme se désabonner aux événements. Lorsque vous utilisez la fonction asynchrone, vous ne pouvez rien renvoyer caruseEffect
je n'attendrai pas le résultatJusqu'à ce que React offre une meilleure façon, vous pouvez créer une aide,
useEffectAsync.js
:Vous pouvez maintenant passer une fonction asynchrone:
la source
useAsyncEffect
telle que vous l'avez écrite pourrait facilement induire quelqu'un en erreur en pensant que s'il retournait une fonction de nettoyage à partir de son effet asynchrone, elle serait exécutée au moment opportun. Cela pourrait conduire à des fuites de mémoire ou à des bogues pires, nous avons donc choisi d'encourager les gens à refactoriser leur code pour rendre la «couture» des fonctions asynchrones interagissant avec le cycle de vie de React plus visible, et le comportement du code en conséquence, espérons-le, plus délibéré et correct.J'ai lu cette question et je pense que la meilleure façon d'implémenter useEffect n'est pas mentionnée dans les réponses. Disons que vous avez un appel réseau et que vous souhaitez faire quelque chose une fois que vous avez la réponse. Par souci de simplicité, stockons la réponse du réseau dans une variable d'état. On peut souhaiter utiliser action / réducteur pour mettre à jour le magasin avec la réponse du réseau.
Référence => https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
la source
L'opérateur void pourrait être utilisé ici.
Au lieu de:
ou
vous pourriez écrire:
C'est un peu plus propre et plus joli.
Les effets asynchrones peuvent provoquer des fuites de mémoire, il est donc important d'effectuer un nettoyage lors du démontage des composants. En cas de récupération, cela pourrait ressembler à ceci:
la source
essayer
la source
Pour les autres lecteurs, l'erreur peut provenir du fait qu'il n'y a pas de parenthèses entourant la fonction asynchrone:
Considérant la fonction async initData
Ce code entraînera votre erreur:
Mais celui-ci ne:
(Notez les crochets autour de initData ()
la source