在这种情况下我应该忽略“react-hooks/exhaustive-deps”吗?

问题描述 投票:0回答:1

考虑以下 React 组件:

const [page, setPage] = useState(1)
const [search, setSearch] = useState("")

const [data, setData] = useState([])

const fetchData = useCallback(() => {
    get({page: page, search: search}.then(setData)
}, [page, search])

useEffect(() => {
    fetchData()
}, [page]) // <----- here I got the react-hooks/exhaustive-deps lint error

// if I add `fetchData` above, `fetchData` will be called whenever `search` change,
// but I only want to fetch data when `page` change.

return <div>
    <Input value={search} setValue={setSearch}/>

    <Button onClick={() => fetchData()}>Search</Button>

    {data.maps(v => <div>{v}</div>}

    <Select value={page} setValue={setPage}/>
</div>

目标很简单:

  • 页面变化时获取数据;
  • 搜索变化时不获取数据;
  • 单击按钮时获取数据;

我真的想不出任何其他方法来绕过 eslint 规则。感谢您的帮助。

reactjs eslint
1个回答
0
投票

这是我能想到的对任何 React linting 规则最常见的反对意见之一,而且这在某种程度上是有道理的——我们对依赖项如何工作的心智模型是它们都是“反应式”的,当它们发生变化时,我们必然想要重新运行效果内部的所有逻辑。

在这种情况下,

search
依赖项属于React文档中“删除不必要的依赖项”下的第二个要点,我们只想读取其最新值:

您可能只想读取某些依赖项的最新值 而不是对其变化做出“反应”。

您可以读取页面的当前参考,并且仅在页面更改时运行您的效果。

const fetchData = useCallback(() => {
  get({
    page: page,
    search: search
  }).then(setData)
}, [page, search])

const prevPageRef = useRef();

useEffect(() => {
  if (prevPageRef.current !== page) {
    fetchData()
  }
}, [page, search])

但是,这给我们带来了非常奇怪的用户体验 - 你说,“搜索发生变化时不要获取数据”。这是否意味着我们只在用户单击更改页面后返回搜索结果,例如在输入字段中键入的文本字符串?这种实现似乎与搜索字段的工作方式违反直觉 - 即,您会立即收到搜索查询的结果,而不是在采取一些后续操作(更改页面)之后。

我想,在实践中,

search
getData()
之间实际上存在一种反应关系。很难想象将方法与搜索依赖关系解耦。

© www.soinside.com 2019 - 2024. All rights reserved.