javascript - 在 useEffect 中针对异步函数的 React Hook 警告: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>
);
}
推荐阅读
- php - 来自 URL 字符串的匹配路由
- java - 使用 Java 流从嵌套列表中查找任何内容
- c++ - 升级 ubuntu 18.04 后链接 libssl 出现未定义的引用错误
- machine-learning - 回归分析的数据归一化
- python - 将 DataFrame 的列设置为 FacetGrid 图形的行
- node.js - Razorpay 签名验证没有发生,因为 SHA256 摘要是错误的 NodeJS
- database - 具有 GROUP BY 和聚合函数的 INNER JOIN 3 个表
- flutter - 水平滚动的粘性标题
- typescript - 运行 tsc 后 VSCode 不显示编译的 JS 文件
- python - 如何让 if elif else 语句重新启动