为什么setState([... arr])会导致重新渲染,而setState(arr)不会导致重新渲染?

时间:2020-10-12 05:39:38

标签: reactjs react-hooks context-api

这些不应该做同样的事情吗?第一个代码段使我的组件重新呈现

private static string Normalize(string input)
{
    return input.ToLower().Replace(" ", "");
}

private static T SetValue<T>(Dictionary<string, object> objectValues) where T : class, new()
{
    var type = typeof(T);
    var instance = new T();
    foreach (var entry in objectValues)
    {
        var prop = type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .First( x => Normalize(x.Name) == Normalize(entry.Key) );
        prop.SetValue(instance, entry.Value);
    }
    return instance;
}

但这不是

const context = React.useContext(myContext);
const { arr, setArr } = context;

const addItem = (item) => {
    arr[0].subArr.push(item);
    setArr([...arr]);
}

setArr刚从React.useState()中拉出,我没有构建自定义功能

2 个答案:

答案 0 :(得分:3)

仅当至少处于其状态(或上下文)中的项目发生更改时,React才会重新渲染该组件。如果所有以前的状态值都为===到新的状态,React将根本不会调用功能组件,而只是继续使用上次呈现的内容。

这是您不应该在React中更改状态的原因之一-它可能导致意外或不可预测的行为。

在您的情况下,当您执行setArr(arr)时,由于arr与状态上下文中的数组完全相同,因此React会跳过重新渲染,因为新状态为===旧状态。仅通过创建一个与当前状态不=== new 数组,才会发生重新渲染。

答案 1 :(得分:0)

要了解这一点,您已经了解了如何在JS中处理数组。用简单的英语来说,当您创建一个数组时,JS会知道该数组的引用,这是存储该数组的内存地址。现在,尽管您正在更改数组中的项目,但不会更改引用。当JS尝试找到该数组时,它将在旧位置找到它。因此,从JS角度来看,尽管更改了项目,但数组没有更改。而且我们知道除非状态发生变化,否则反应不会重新呈现。因此,当您编写setState(arr)时,react发现数组引用未更改,因此没有重新渲染。

另一方面,当您编写setState([... arr])时,我们正在使用arr数组的项目创建一个新数组。因此,在这种情况下,react发现数组引用已更改。因此,它重新呈现。

为了更好地理解,您应该阅读此thread