React Hooks useState 与 Object 不一致

React Hooks useState is not consistent with Object

我有这段代码。

import React, { useState, useEffect } from 'react';
export default function Example() {
const [object, setObject] = useState({
    count: 0
});

const onClick = () => {
    setObject(old => {
        old.count = old.count + 1;
        return old;
    });
};

return (
    <div>
        <p>You clicked {object.count} times</p>
        <button onClick={e => console.log(object.count)}>Show in log</button>
        <button onClick={onClick}>Click me</button>
    </div>
);
}

如果单击 "Click me",将增加对象的计数 属性。 但是由于某些原因,如果您单击它,对象仍然会更新,但组件不会重新渲染。您可以使用 "Show in log" 按钮检查对象的值。

根据reactjs.org,每当您设置组件的状态时,它都会重新渲染。但是这样写就不行了

但是如果我将 onClick 函数更改为

const onClick = () => {
    setObject(oldObject => {
        const newObject = { ...oldObject };
        newObject.count = oldObject.count + 1;
        return newObject;
    });
};

然后它将重新渲染组件。

任何人都可以解释导致这种奇怪行为的原因吗?

您在第一个代码片段中所做的事情 改变了 原始状态——这在 React 中几乎总是 大忌世界。 React 通常仅在某些状态或道具发生变化时才重新渲染,并且由于您改变了原始状态,因此看起来状态并没有发生变化。

在您的第二个示例中,您创建了原始状态的副本 (const newObject = {...oldObject})。改变副本并返回它很好——你没有改变原始状态。

尝试像这样设置 object

const onClick = () => {
  setObject({
    count: object.count + 1
  });
};

您需要return反对。你不是 returning 正确的对象。尝试这样做:

const onClick = () => {
    // setObject({...object, count:object.count+1}); //another way

    setObject(old => {
      console.log(old)
        let updatedCount = old.count + 1
        return {...old,count: updatedCount};
    });
};

实例:https://stackblitz.com/edit/react-sfjzgz

setObject 是一个调度函数。 React 设计它的方式,你唯一需要提供的是一个新值,这个值被认为是一个改变的状态。

你所做的是,你向调度函数提供一个函数类型,然后改变作为函数参数给你的对象。

你做什么

const onClick = () => {
    setObject(old => { // <-- a function is provided here
        old.count = old.count + 1;
        return old;
    });
};

你需要做什么

const onClick = () => {
    setObject({...object, count: object.count + 1});
    // this way no mutation of the original state value is happening, 
    //and you are guaranteed to have a re-render.
};

并且请停止调用变量 objectsetObject 我知道这只是一个例子,但是发布这个代码片段很可能会得到你对 type/name 情况感到困惑。

之所以会这样是因为 React 使用 Object.is comparison algorithm.

如果您将 State Hook 更新为与当前状态相同的值,React 将在不渲染子项或触发效果的情况下退出。