考虑以下 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 规则。感谢您的帮助。
这是我能想到的对任何 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()
之间实际上存在一种反应关系。很难想象将方法与搜索依赖关系解耦。