反应 useEffect 警告

时间:2021-06-27 13:18:27

标签: reactjs typescript

我有这个组件和下面的界面

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


}

而且两个 useEffect 都在给我警告

第一个是这样的,因为我使用它就好像它是一个 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 在依赖数组中有一个复杂的表达式。 将其提取到一个单独的变量中,以便它可以是静态的 已检查.eslintreact-hooks/exhaustive-deps

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

4 个答案:

答案 0 :(得分:2)

这应该会有所帮助:

  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(状态变量)保存相同的数据。如果您选择这样做,请确保这是一个有意识的决定。

答案 1 :(得分:1)

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

您应该在props.data依赖数组中添加useEffect,或者您可以直接使用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 :(得分:1)

这将解决两个警告行为没有任何改变

 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 :(得分:0)

第一个 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 更改时重新运行效果,但如果 setCandleWidth 不为 0,则仅 data.length