React Hooks useState 与 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>
);
}

如果单击"单击我",它将增加对象的 count 属性。但由于某些原因,如果单击它,对象仍会更新,但组件不会重新渲染。您可以使用"在日志中显示"按钮检查对象的值。

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

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

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

然后它将重新渲染组件。

谁能解释一下是什么导致了这种奇怪的行为?

它之所以以这种方式运行,是因为 React 使用了 Object.is 比较算法。

如果你将状态钩子更新为与当前状态相同的值,React 将拯救而不渲染子项或触发效果。

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

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

您需要返回对象。 您没有返回正确的对象。尝试这样做:

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

尝试像这样设置object

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

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.
};

请停止调用变量对象setObject 我知道这只是一个例子,但发布此代码片段很可能会让您对类型/名称情况感到困惑。

相关内容

  • 没有找到相关文章