我正在尝试以下useEffect示例:
useEffect
useEffect(async () => { try { const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`); const json = await response.json(); setPosts(json.data.children.map(it => it.data)); } catch (e) { console.error(e); } }, []);
我在控制台中收到此警告。但是我认为清理对于异步调用是可选的。我不确定为什么会收到此警告。以链接沙箱为例。https://codesandbox.io/s/24rj871r0p
我建议在这里查看Dan Abramov(React 核心维护者之一)的答案:
我认为你让它变得比它需要的更复杂。
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> }
从长远来看,我们将不鼓励这种模式,因为它鼓励竞争条件。比如——在你的通话开始和结束之间任何事情都可能发生,你可能会得到新的道具。相反,我们会推荐 Suspense 用于数据获取,它看起来更像
const response = MyAPIResource.read();
并且没有效果。但与此同时,您可以将异步内容移至单独的函数并调用它。
您可以在此处阅读有关实验悬念的更多信息。
如果你想在 eslint 之外使用函数。
function OutsideUsageExample({ userId }) { const [data, dataSet] = useState<any>(null) const fetchMyAPI = useCallback(async () => { let response = await fetch('api/data/' + userId) response = await response.json() dataSet(response) }, [userId]) // if userId changes, useEffect will run again useEffect(() => { fetchMyAPI() }, [fetchMyAPI]) return ( <div> <div>data: {JSON.stringify(data)}</div> <div> <button onClick={fetchMyAPI}>manual fetch</button> </div> </div> ) }
如果您使用 useCallback,请查看 useCallback 的工作原理示例。沙盒。
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> ); }