我有一个用例,页面必须在第一次渲染和单击按钮时调用相同的 fetch 函数。
代码与以下类似(引用:https://stackblitz.com/edit/stackoverflow-question-bink-62951987?file=index.tsx):
import React, { FunctionComponent, useCallback, useEffect, useState } from 'react';
import { fetchBackend } from './fetchBackend';
const App: FunctionComponent = () => {
const [selected, setSelected] = useState<string>('a');
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<boolean>(false);
const [data, setData] = useState<string | undefined>(undefined);
const query = useCallback(async () => {
setLoading(true)
try {
const res = await fetchBackend(selected);
setData(res);
setError(false);
} catch (e) {
setError(true);
} finally {
setLoading(false);
}
}, [])
useEffect(() => {
query();
}, [query])
return (
<div>
<select onChange={e => setSelected(e.target.value)} value={selected}>
<option value="a">a</option>
<option value="b">b</option>
</select>
<div>
<button onClick={query}>Query</button>
</div>
<br />
{loading ? <div>Loading</div> : <div>{data}</div>}
{error && <div>Error</div>}
</div>
)
}
export default App;
我的问题是 fetch 函数总是在任何输入更改时触发,因为 eslint-plugin-react-hooks
强制我在 useCallback
中声明所有依赖项(例如:选定状态)钩。我必须使用 useCallback
为了与 useEffect
一起使用.我知道我可以将函数放在组件之外并传递所有参数(props、setLoading、setError、..etc)以使其正常工作,但我想知道是否可以在保留相同效果的同时存档组件内部的 fetch 函数并遵守
eslint-plugin-react-hooks
?[更新]
对于有兴趣查看工作示例的任何人。这是从接受的答案派生的更新代码。
https://stackblitz.com/edit/stackoverflow-question-bink-62951987-vxqtwm?file=index.tsx
最佳答案
将所有依赖项添加到 useCallback
像往常一样,但不要在 useEffect 中创建另一个函数:useEffect(query, [])
对于异步回调 (如您的情况下的查询),您需要使用带有 .then
的旧式 promise 方式, .catch
和 .finally
回调,以便将 void 函数传递给 useCallback
,这是 useEffect
所要求的.
另一种方法可以在 React's docs 上找到。 ,但根据文档不建议这样做。
毕竟,内联函数传递给 useEffect
无论如何都会在每次重新渲染时重新声明。使用第一种方法,您将仅在查询的部门发生变化时传递新函数。警告也应该消失。 ;)
关于javascript - 与 useEffect 一起使用时如何防止 useCallback 触发(并遵守 eslint-plugin-react-hooks)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62951987/