javascript - 与 useEffect 一起使用时如何防止 useCallback 触发(并遵守 eslint-plugin-react-hooks)?

标签 javascript reactjs typescript react-hooks eslint-plugin-react-hooks

我有一个用例,页面必须在第一次渲染和单击按钮时调用相同的 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/

相关文章:

javascript - 这个简单的 chrome 扩展有什么问题?

javascript - 使用鼠标拖动来控制背景位置

reactjs - React-Transition-Group 在添加 *-enter 类之前添加延迟

javascript - 为 JSON 属性抛出 Nan 消息

angular - 测试带有订阅的 typescript 函数

javascript - 如果 <p> 中的文本是 X 然后 addClass

javascript - 在 javascript 和 PHP 之间发送 JSON 字符串的正确方法是什么?

javascript - React - 为react-i18next调用useTranslation时无效的钩子(Hook)调用

javascript - 将缓冲区数组转换为图像

javascript - Google-Maps-React 与 TypeScript。参数错误