【问题标题】:Component not re-rendering after change in an object state in React反应,组件在对象状态更改后不重新渲染
【发布时间】:2022-07-12 18:29:38
【问题描述】:

还有其他多个 Stack Overflow 线程与此问题有点相关,但实际上标题含糊不清,或与带有类组件的 React 相关,或与非常复杂的 React 组件或状态相关。因此,我想创建一个能够明确且真正简单地解决将 state 更改为 object 时出现的问题。

请注意,我正在单击 user 对象的 firstName 属性进行更新,这是一个状态,没有任何事情发生。代码如下:

const App = () => {
  const [user, setUser] = React.useState({ firstName: "Jhon", lastName: "Doe", tel:"09004345000" });
  const changeFirstAndLastName = () => {
    const newUser = user;
    newUser.firstName = "David";
    setUser(newUser);
  };
  return (
    <div>
      <div>
        <p>First Name: {user.firstName}</p>
        <p>Last Name: {user.lastName}</p>
        <p>Tel: {user.tel}</p>
      </div>
      <button onClick={changeFirstAndLastName}>
        Change First Name
      </button>
    </div>
  );
}
ReactDOM.render(
    <App />,
    document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    React 不会重新渲染,因为它就像什么都没有改变,即每次你将相同的 state 提供给 setState 时。对于像 NumberStringBoolean 这样的原始值,很明显知道我们是否给出了不同的值。

    另一方面,对于ObjectArray 等引用值,更改它们的content 不会将它们标记为不同。应该是不同的内存reference。查看您的注释代码以了解您做错了什么:

    const newUser = user;         // will do a reference copy => newUser == user
    newUser.firstName = "David"; // will change its content => newUser == user
    setUser(newUser);           // at this point it's like nothing has changed
    

    一个解决方案可能是spread operator,它将创建现有对象的副本但在新的内存引用上,就像这样(注意你可以避免使用这个newUser中间变量):

    // changes the content of the array while keeping its memory reference
    subNames.splice(position, 1); 
    // the spread operator creates a copy on a new memory reference
    setUser({...user, firstName: "David", lastName: "Owen"}); 
    

    工作示例:

    const App = () => {
      const [user, setUser] = React.useState({ firstName: "Jhon", lastName: "Doe", tel:"09004345000" });
      const changeFirstAndLastName = () => {
        setUser({...user, firstName: "David"}); 
      };
      return (
        <div>
          <div>
            <p>First Name: {user.firstName}</p>
            <p>Last Name: {user.lastName}</p>
            <p>Tel: {user.tel}</p>
          </div>
          <button onClick={changeFirstAndLastName}>
            Change first and last name
          </button>
        </div>
      );
    }
    ReactDOM.render(
        <App />,
        document.getElementById('root')
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    【讨论】:

      猜你喜欢
      • 2017-03-24
      • 2022-07-08
      • 2021-01-27
      • 1970-01-01
      • 2021-06-20
      • 2019-04-03
      • 2023-03-22
      • 2020-10-07
      • 1970-01-01
      相关资源
      最近更新 更多