【问题标题】:React useEffect warnings反应 useEffect 警告
【发布时间】:2021-09-10 01:31:57
【问题描述】:

我有这个组件和如下界面

interface IProps {
  data: Array<{
    low: number,
    high: number,
    open: number,
    close: number,
    openTime: number
  }>
}


const Canvas: React.FC<IProps> = (props) => {
 const [data, setData] = useState<Array<{
    low: number,
    high: number,
    open: number,
    close: number,
    openTime: number
  }>>();
}

useEffect(() => {
    setData(props.data)
  }, []) //warning1

  useEffect(() => {
    const canvas: any = canvasRef.current;
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    if (data) {
      setCandleWidth(canvas.width / data.length)
    }
  }, [data && data.length != 0]) //Warning2


}

两个useeffects都给我警告

第一个就是这样,因为我使用它就好像它是一个 componentDidMount() ,但它说

React Hook useEffect 缺少一个依赖项:'props.data'。任何一个 包含它或删除依赖数组。如果“setData”需要 'props.data' 的当前值,也可以切换到 useReducer 而不是 useState 并在 reducer 中读取“props.data”。

第二个说如下,而我只是想在设置数据后触发它

React Hook useEffect 缺少一个依赖项:'data'。要么包括 它或删除依赖 array.eslintreact-hooks/exhaustive-deps React Hook useEffect 在依赖数组中有一个复杂的表达式。 将其提取到一个单独的变量中,以便它可以是静态的 checked.eslintreact-hooks/exhaustive-deps

那么有什么更好的方法来做到这一点?

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    这是因为,useEffect 只会运行一次,因为没有依赖关系,并且您只是通过在 useEffect 中添加带有空数组的 setData 来初始化状态(可以说)。

    您应该在useEffect依赖数组中添加props.data,或者您可以直接使用useState初始化数据。

    const [data, setData] = useState(props.data);
    
    // OR 
    
    useEffect(() => {
        setData(props.data)
    }, [props.data]) 
    
    

    关于警告 2: 您正在计算依赖数组中的布尔值。这不会触发它重新渲染。最好在数组中添加data 并在给定的函数内部进行检查。 useEffect

    
     useEffect(() => {
        const canvas: any = canvasRef.current;
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        if (data && data.length != 0 {
          setCandleWidth(canvas.width / data.length)
        }
      }, [data])
    
    

    【讨论】:

      【解决方案2】:

      这将修复两个警告行为没有任何变化

       useEffect(() => {
          setData(props.data)
          // eslint-disable-next-line react-hooks/exhaustive-deps
       }, []) 
      
      
      
       useEffect(() => {
          const canvas: any = canvasRef.current;
          canvas.width = window.innerWidth;
          canvas.height = window.innerHeight;
          if (data) {
            setCandleWidth(canvas.width / data.length)
          }
       }, [data])
      

      【讨论】:

        【解决方案3】:

        第一个useEffect其实没问题。这只是一个 ESLint、TSLint 警告——那些 linter 非常不喜欢空的依赖数组。如果你绝对确定你想使用一个空数组作为依赖数组(从而使效果在初始挂载时只运行一次),你可以在该行旁边添加ESLint disable as a comment

        至于第二个useEffect,您使用的依赖数组有点错误。依赖数组仅用于列出依赖项——即 React 将监视哪些更改;它是用来列出东西的,不应该有逻辑。如果您需要条件渲染的逻辑,可以将其放在效果中,例如@Shreyas Jadhav 的回答

        useEffect(() => {
            const canvas: any = canvasRef.current;
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            if (data && data.length != 0) {
              setCandleWidth(canvas.width / data.length)
            }
          }, [data])
        

        第二个useEffect 现在意味着,只要data 更改,就会重新运行效果,但如果data.length 不为0,则只有setCandleWidth

        【讨论】:

          【解决方案4】:

          这应该会有所帮助:

          1. 我已经删除了第一个 useEffect 并将数据直接传递给状态。
          2. 我已经在另一个 useEffect 中编辑了依赖数组。

          const [data, setData] = useState(props.data);
          
          useEffect(() => {
              const canvas: any = canvasRef.current;
              canvas.width = window.innerWidth;
              canvas.height = window.innerHeight;
              if (data) {
                  setCandleWidth(canvas.width / data.length)
              }
          }, [data])
          

          旁注:

          您通常不想复制数据。 props.datadata(状态变量)持有相同的数据。如果您选择这样做,请确保这是一个有意识的决定。

          【讨论】:

            猜你喜欢
            • 2022-01-08
            • 2020-05-06
            • 2021-10-14
            • 2020-09-03
            • 2020-02-21
            • 2021-07-12
            • 2022-01-02
            • 1970-01-01
            • 2021-04-02
            相关资源
            最近更新 更多