簡體   English   中英

如何將缺少的依賴項添加到只運行一次的 useEffect 鈎子?

[英]How to add missing dependencies to a useEffect hook that is run only once?

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 警告?

似乎對我useCallback()是將間隔的邏輯分離到一個沒有依賴關系的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>
  )
}

解決方案是從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);
}, []);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM