Reactjs 如何避免useEffect钩子中的递归依赖

Reactjs 如何避免useEffect钩子中的递归依赖,reactjs,react-hooks,Reactjs,React Hooks,我有一个组件,它维护一个随时间提取的项目列表。组件在加载时获取一个项目,并且还可以在用户交互的结果中获取新项目。无论何时提取项目,都应将其添加到项目列表中。下面的代码进入无限递归,因为每次我向items添加一个新项时,效果会再次通过新的items列表调用,并添加另一个项 export default function UnintentionallyRecursive () { const [item, setItem] = useState() const [items, setItem

我有一个组件,它维护一个随时间提取的项目列表。组件在加载时获取一个项目,并且还可以在用户交互的结果中获取新项目。无论何时提取项目,都应将其添加到项目列表中。下面的代码进入无限递归,因为每次我向
items
添加一个新项时,效果会再次通过新的
items
列表调用,并添加另一个项

export default function UnintentionallyRecursive () {
  const [item, setItem] = useState()
  const [items, setItems] = useState([])

  const fetchItem = () => new Promise(resolve => resolve({ title: 'a new item' }))

  const updateItem = useCallback(async () => {
    const newItem = await fetchItem()
    setItem(newItem)
  }, [setItem])

  useEffect(() => {
    updateItem()
  }, [updateItem])

  // this is the part that causes the recursion
  useEffect(() => {
    setItems(items.concat([item]))
  }, [item, items, setItems])

  return null // really UI code which can also call updateItem
}

如何使用钩子实现这一点?

您可以使用函数的当前状态作为参数来更新状态。这样,您就不需要将
项作为依赖项

setItems((currentState) => currentState.concat(item));

// is the same as
setItems([items].concat(item));

旁注:您也不需要将
setItems
添加到依赖项数组中,它可以保存以省去。

您可以使用函数更新状态,并将其当前状态作为参数。这样,您就不需要将
项作为依赖项

setItems((currentState) => currentState.concat(item));

// is the same as
setItems([items].concat(item));

旁注:您也不需要将
setItems
添加到依赖项数组中,它可以保存以省去。

直到
中的
功能更新
useState

用此函数替换有问题的
useffect
调用修复了该问题

  useEffect(() => {
    setItems(items => items.concat([item]))
  }, [item, setItems])


直到
useState

用此函数替换有问题的
useffect
调用修复了该问题

  useEffect(() => {
    setItems(items => items.concat([item]))
  }, [item, setItems])


比我快30秒:)比我快30秒:)