Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 反应重新渲染循环_Arrays_Reactjs_Dependencies_State_Render - Fatal编程技术网

Arrays 反应重新渲染循环

Arrays 反应重新渲染循环,arrays,reactjs,dependencies,state,render,Arrays,Reactjs,Dependencies,State,Render,我目前正试图了解React的内部工作原理,它是在组件被重新呈现或者(回调)函数被重新创建的情况下进行的 在这样做的过程中,我遇到了一个我无法理解的现象。它(仅)在具有包含数组的状态时发生。下面是显示“问题”的最基本代码: 调试显示,重新呈现是由于onChange被更改而发生的。然而,我不明白这一点。为什么要更改onChange?内部状态和状态都不会在任何地方更改 我发现有两种变通方法: 从子对象中效果的依赖项中删除onChange。这“解决”了重新渲染问题,对于我的用例来说是绝对可以接受的。然而

我目前正试图了解React的内部工作原理,它是在组件被重新呈现或者(回调)函数被重新创建的情况下进行的

在这样做的过程中,我遇到了一个我无法理解的现象。它(仅)在具有包含数组的状态时发生。下面是显示“问题”的最基本代码:

调试显示,重新呈现是由于
onChange
被更改而发生的。然而,我不明白这一点。为什么要更改
onChange
?内部状态和状态都不会在任何地方更改

我发现有两种变通方法:

  • 从子对象中效果的依赖项中删除
    onChange
    。这“解决”了重新渲染问题,对于我的用例来说是绝对可以接受的。然而,据我所知,这是一种不好的做法,因为
    onChange
    在效果中使用。此外,ESLint将此指示为警告
  • 在状态中使用“原始”数字,而不是数组。这也将消除重新渲染。然而,这仅在这个最小的示例中是可以接受的,因为只使用了一个数字。对于动态数字计数,此解决方案不可行
  • useCallback
    也没有帮助,只是“冒泡”重新创建了
    onChange
    函数

    所以我的问题是:React state(包括数组)更新的处理方式是否不同,是否省略了一个在这里有效的依赖项?正确的方法是什么

    为什么onChange会被改变

    在每次渲染时,都创建一个新的匿名函数
    (v)=>setState([v])

    由于在渲染之前与以前的道具进行了浅层比较,因此始终会导致渲染,因为在Javascript中:

    const y = () => {}
    const x = () => {}
    
    x !== y // always true
    
    // In your case
    const onChangeFromPreviousRender = (v) => setState([v])
    const onChangeInCurrentRender = (v) => setState([v])
    
    onChangeFromPreviousRender !== onChangeInCurrentRender
    
    正确的方法是什么

    有两种方法可以纠正它,因为
    setState
    保证是稳定的,所以您可以通过setter并在组件本身中使用您的逻辑:

    // state[0] is primitive
    // setState stable
    <Child value={state[0]} onChange={setState} />
    
      useEffect(() => {
        // set as array
        onChange([internalValue]);
      }, [onChange, internalValue]);
    
    请注意,我们之所以记住函数,只是因为它的非平凡用例(注意过早优化)

    const y = () => {}
    const x = () => {}
    
    x !== y // always true
    
    // In your case
    const onChangeFromPreviousRender = (v) => setState([v])
    const onChangeInCurrentRender = (v) => setState([v])
    
    onChangeFromPreviousRender !== onChangeInCurrentRender
    
    // state[0] is primitive
    // setState stable
    <Child value={state[0]} onChange={setState} />
    
      useEffect(() => {
        // set as array
        onChange([internalValue]);
      }, [onChange, internalValue]);
    
    const onChange = useCallback(v => setState([v]), []);