React Hooks useState与Object不一致

时间:2019-07-15 07:30:42

标签: reactjs react-hooks

我有这段代码。

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

然后它将重新渲染组件。

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

5 个答案:

答案 0 :(得分:1)

您在第一个代码段中所做的工作更改了原始状态-在React世界中,这几乎总是不可行。通常,React通常仅在某些状态或道具已更改的情况下才转售,并且由于您对原始状态进行了突变,因此状态看起来似乎没有更改。

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

答案 1 :(得分:0)

尝试像这样设置object

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

之所以如此行事,是因为React使用Object.is comparison algorithm

如果将状态挂钩更新为与当前状态相同的值,React将纾困,而不会渲染子代或发射效果。