如何避免useEffect挂钩中的递归依赖项

时间:2019-12-02 23:30:30

标签: reactjs react-hooks

我有一个组件,用于维护随时间推移获取的项目的列表。该组件在加载时获取项目,并且还可以由于用户交互而获取新项目。每当获取项目时,都应将其添加到项目列表中。以下代码进行无限递归,因为每次我将新项目添加到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
}

如何使用Hooks实现此目的?

2 个答案:

答案 0 :(得分:1)

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

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

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

旁注:您也不需要在依赖项数组中添加setItems,省去了。

答案 1 :(得分:0)

functional updatesuseState的TIL

为此替换了有问题的useEffect呼叫

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