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 } }, [])