【问题标题】:How to add missing dependencies to a useEffect hook that is run only once?如何将缺少的依赖项添加到仅运行一次的 useEffect 挂钩?
【发布时间】:2021-03-03 07:40:19
【问题描述】:

React Hook useEffect 缺少依赖项:'myDate' 和 'setMyDate'。要么包含它们,要么移除依赖数组。

如何将缺少的依赖项添加到只运行一次的useEffect?以下示例生成上述警告:

const [ myDate, setMyDate ] = useState(0)

const spinner = useRef(null)
useEffect( () => {
    spinner.current = setInterval( () => {
        d = Date.now()
        if (d < myDate)
            setUpdate(d)
    }, 997 )
}, [])

如果我包含它们,我会创建一个无限循环,因为 setTimeout 会更改依赖项的值:

const spinner = useRef(null)
useEffect( () => {
    spinner.current = setInterval( () => {
        d = Date.now()
        if (d < myDate)
            setMyDate(d)
    }, 997 )
}, [myDate, setMyDate])

如果我删除依赖数组,useEffect 在每次渲染上运行,并设置无限数量的 setIntervals:

const spinner = useRef(null)
useEffect( () => {
    spinner.current = setInterval( () => {
        d = Date.now()
        if (d < myDate)
            setMyDate(d)
    }, 997 )
})

我还尝试完全删除useEffect,认为由于spinneruseRef,它不会在每个组件渲染上重新分配...但没有:

const spinner = useRef(null)
spinner.current = setInterval( () => {
    d = Date.now()
    if (d < myDate)
        setMyDate(d)
}

也尝试过使用功能更新方法,就像这样,但是 lint 错误仍然存​​在并且代码不起作用:

const spinner = useRef(null)
useEffect( () => {
    spinner.current = setInterval( () => {
        d = Date.now()
        setMyDate(d => {
            if (d < myDate)
                setMyDate(d)
        }
    }, 997 )
}, [setMyDate])

我被卡住了……夹在石头和坚硬的地方之间!如何解决此 lint 警告?

【问题讨论】:

  • 我不知道它是否会起作用,因为有时我有奇怪的无限循环,因为方法没有改变。您可以做的是创建一个设置间隔的方法,并通过将其分配为依赖项来在使用效果中调用此方法。通常它会起作用,因为就像我说的那样,方法不会改变。
  • 你想做什么?
  • @Galupuf 创建一次setInterval,每n秒调用一次钩子更新。

标签: reactjs dependencies react-hooks use-effect use-ref


【解决方案1】:

解决方案是从setMyDate 函数本身获取myDate(在我的代码中命名为date),而不是将其作为依赖项传递。

setMyDate 已被记忆,因此不需要作为依赖项传递。

const [myDate, setMyDate] = useState(0);
const spinner = useRef(null);

useEffect(() => {
  spinner.current = setInterval(() => {
    const d = Date.now();

    setMyDate(date => {
      if (d < date) {
        return d;
      }
      return date;
    });
  }, 997);
}, []);

【讨论】:

  • 不错...功能更新方法。就我而言,myDatesetMyDateuseContext 钩子,所以 linter 仍在抱怨 setMyDate
  • @kmiklas 这确实有所作为,您应该在问题中对此进行解释。请编辑您的帖子并添加相关钩子的代码。
  • 瓦伦丁谢谢你。我打算做一个最小的例子。
【解决方案2】:

似乎对我有用的是将间隔的逻辑分离到一个没有依赖关系的useCallback() 钩子中。这会记住函数并确保该函数仅在初始组件渲染上构建。

然后,在效果内部调用使用useCallback() 构建的函数,并将其提供给效果依赖项数组。然后,只有在 useCallback() 函数发生变化时才会重建效果——它不会因为它没有依赖关系而重建。

应该从 react-hooks 中删除 linter 警告

import React, {useState, useEffect, useRef, useCallback} from 'react'

export default function IntervalHook() {

  const [ myDate, setMyDate ] = useState(0)
  const spinner = useRef(0)

  const spinnerFn = useCallback(() => {
    spinner.current = setInterval(() => {
      const d = Date.now()
      setMyDate(d)
    }, 997 )
  }, [])

  useEffect(() => {
    spinnerFn()     
    return () => {  // this return statement clears the interval when the component unmounts
      if (spinner.current) {
        clearInterval(spinner.current)
        spinner.current = 0
      }
    }
  }, [spinnerFn])

  return (
    <span>{myDate}</span>
  )
}

【讨论】:

    猜你喜欢
    • 2020-09-03
    • 2020-05-21
    • 2020-02-13
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    • 2020-06-18
    • 2021-02-23
    相关资源
    最近更新 更多