【问题标题】:React Hooks: Handling Objects as dependency in useEffectsReact Hooks:将对象作为 useEffect 中的依赖项处理
【发布时间】:2020-02-13 18:47:33
【问题描述】:

更新:对于用例 1 是的,如果我在 useEffect 之外提取 search.value 并将其用作依赖项,它就可以工作。

但我在下面有一个更新的用例

用例 2:我想将 searchHits 对象传递给服务器。服务器反过来将它返回给我,并以更新的值作为响应。 如果我尝试使用 searchHits 对象,我仍然会得到无限循环

state: {
    visible: true,
    loading: false,
    search: {
        value: “”,
        searchHits: {....}, 
        highlight: false,
    }
}

let val = search.value
let hits = search.searchHits
useEffect( () => {

    axios.post(`/search=${state.search.value}`, {hits: hits}).then( resp => {
        …do something or ..do nothing
        state.setState( prevState => {
            return {
                …prevState,
                search: {... prevState.search, hits: resp.hit}
            }
        })
    })
}, [val, hits])

用例 1:我想搜索一个字符串,然后在得到结果时突出显示

例如

state: {
    visible: true,
    loading: false,
    search: {
        value: “”,
        highlight: false,
    }
}

useEffect( () => {

    axios.get(`/search=${state.search.value}`).then( resp => {
        …do something or ..do nothing
        state.setState( prevState => {
            return {
                …prevState,
                search: {... prevState.search, highlight: true}
            }
        })
    })
}, [state.search])

在 useEffect 中,我使用 search.value 进行 API 调用。 eslint 抱怨存在对 state.search 的依赖,它无法识别 state.search.value。即使你通过了state.search.value,它也会抱怨state.search

现在,如果您将 state.search 作为依赖项传递,它将进入无限循环,因为在 api 调用之后,我们正在更新搜索中的 highlights 标志。

这将触发另一个状态更新和递归循环。

避免这种情况的一种方法是不要将嵌套对象置于状态或将高亮标志移动到搜索之外,但我试图不走这条路线,因为我拥有纯粹的依赖。 我宁愿有一个处于状态的对象,称为搜索。有没有办法更好地解决这个问题。 如果我想保持我的状态对象如上,我该如何处理无限循环

【问题讨论】:

  • 这是 linter 及其与 react-hooks 交互的一个持续问题。您的代码没有什么特别的问题。照原样,忽略此警告是安全的。
  • 如果这是一个 esLint 问题,我很乐意忽略,但我真的很想确定。因为只有当我们在依赖项中使用对象时才会出现问题
  • 避免使用带有 useState 的大对象。如果必须,请改用 useReducer。
  • @SamerBuna 我已经使用了 useReducers 并且它仍然进入一个循环。

标签: javascript reactjs react-hooks use-effect


【解决方案1】:

可能只是一个 eslint 的东西错误。您通过说//do something 撤回了一些代码并隐藏了他的代码。您确定它与搜索对象没有任何关系吗?

另外,尝试在useEffect()之前提取变量。

const searchValue = state.search.value; useEffect(()=>{// axios call here},[searchValue])

如果您的搜索值是一个对象,react 会进行浅层比较,它可能不会给出想要的结果。在一组对象依赖项上重新渲染并不理想。提取变量。

React 对 useEffect 中指定的依赖项进行浅层比较

例如,

const {searchParam1, searchParam2} = search.value;
useEffect(() => {
//logic goes here
}, [searchParam1, searchParam2]);

此外,您可以为 eslint-plugin-react-hooks 添加 dev 依赖项,以识别 hooks 的常见错误

【讨论】:

  • 做某事没有任何意义,可以删除。是的,将变量提取出来是有效的,但它只有效,因为 search.value 是一个字符串。如果 search.value 是一个对象,它仍然会进入无限循环
  • @StallionV 将对象作为 useEffect 依赖项传递是个坏主意。通常,您不希望基于对象重新渲染,而是基于变量集。 React 会对对象进行浅层比较,而不是深度比较。因此,从 search.value 中提取您需要的所有变量并将它们添加为依赖项。将更新答案
  • 我明白这一点。但是,您如何解决基于 API 响应更新 State 对象的问题。 API 必须与 useEffect 一起使用,如果我想将该对象发布到服务器,它必须是一个依赖项。现在在这种情况下,我如何根据服务器响应进行更新并避免无限循环
  • 在实际情况下考虑这一点。您正在使用效果意味着您希望这些数据基于开始时的一些变量。如果您希望这种情况只发生一次,则将空 [] 作为依赖项传递,否则如果您希望将其作为变量更改,请将它们添加为依赖项。通常,post on useEffect 是一个罕见的电话,我想知道哪些情况适用。
  • 这种情况可能是您将一些数据对象从您的状态传递给服务器,服务器反过来会处理数据并对其进行更改并将其传回给您。您现在需要将该数据更新回该状态。
猜你喜欢
  • 2020-09-22
  • 2019-11-26
  • 2020-01-16
  • 2020-12-07
  • 2021-02-23
  • 2021-08-19
  • 2021-07-28
  • 2020-10-26
相关资源
最近更新 更多