Ich schlage vor, die Antwort von Dan Abramov (einem der Hauptbetreuer von React) hier zu lesen :
Ich denke, Sie machen es komplizierter als es sein muss.
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>
}
Längerfristig werden wir von diesem Muster abraten, da es die Rennbedingungen fördert. Zum Beispiel könnte zwischen dem Beginn und dem Ende Ihres Anrufs alles passieren, und Sie hätten neue Requisiten bekommen können. Stattdessen empfehlen wir Suspense für das Abrufen von Daten, das eher so aussieht
const response = MyAPIResource.read();
und keine Effekte. In der Zwischenzeit können Sie das asynchrone Material in eine separate Funktion verschieben und aufrufen.
Mehr über experimentelle Spannung können Sie hier lesen .
Wenn Sie Funktionen außerhalb mit eslint verwenden möchten.
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>
)
}
Mit useCallback useCallback . Sandkasten .
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 } }, [])