简体   繁体   English

除非刷新页面,否则 React useState 不会立即更新

[英]React useState does not update immediately unless refresh page

I have the following component with a state that keep tracks of checkboxes:我有以下组件,其状态可以跟踪复选框:

import { useState } from "react";

function SideBar() {
  const [queryObject, setQueryObject] = useState({
    genders: [],
    availabilities: []
  });
  function handleChange(event) {
    const { name, checked } = event.target;

    if (name === "male" || name === "female") {
      if (checked) {
        setQueryObject((prevQueryObject) => {
          prevQueryObject.genders.push(name);
          return prevQueryObject;
        });
      } else {
        setQueryObject((prevQueryObject) => {
          return prevQueryObject.genders.filter((e) => e !== name);
        });
      }
      return;
    }

    if (name === "available" || name === "not available") {
      if (checked) {
        setQueryObject((prevQueryObject) => {
          prevQueryObject.availabilities.push(name);
          return prevQueryObject;
        });
      } else {
        setQueryObject((prevQueryObject) => {
          return prevQueryObject.availabilities.filter((e) => e !== name);
        });
      }
      return;
    }
  }

  return (
    <div>
      <input
        type="checkbox"
        checked={queryObject.genders.includes("male")}
        onChange={handleChange}
        name="male"
      />
      <span>Male</span>
      <input
        type="checkbox"
        checked={queryObject.genders.includes("female")}
        onChange={handleChange}
        name="female"
      />
      <span>Female</span>
      <br />
      <input
        type="checkbox"
        checked={queryObject.availabilities.includes("available")}
        onChange={handleChange}
        name="available"
      />
      <span>Available</span>
      <input
        type="checkbox"
        checked={queryObject.availabilities.includes("not available")}
        onChange={handleChange}
        name="not available"
      />
      <span>Not available</span>
    </div>
  );
}

export default SideBar;


When I tried to click on the checkboxes it does not update immediately, I found that whenever I save my text file again the browser reloads and then it updates, I think the problem is in my handleChange function, is the way I'm handling the setQueryObject wrong ?当我尝试单击它不会立即更新的复选框时,我发现每当我再次保存我的文本文件时,浏览器都会重新加载然后更新,我认为问题出在我的 handleChange 函数中,这是我处理的方式setQueryObject 错了?

Thanks to Yury i re-wrote the code and it works感谢Yury ,我重新编写了代码并且它可以工作

import { useState } from "react";

function SideBar() {
  const [queryObject, setQueryObject] = useState({
    genders: [],
    availabilities: []
  });
  function handleChange(event) {
    const { name, checked } = event.target;

    if (name === "male" || name === "female") {
      if (checked) {
        setQueryObject((prevQueryObject) => {
          return {
            ...prevQueryObject,
            genders: prevQueryObject.genders.concat(name)
          };
        });
      } else {
        setQueryObject((prevQueryObject) => {
          return {
            ...prevQueryObject, 
            genders: prevQueryObject.genders.filter((e) => e !== name)
          }
        });
      }
      return;
    }

    if (name === "available" || name === "not available") {
      if (checked) {
        setQueryObject((prevQueryObject) => {
          return {
            ...prevQueryObject,
            availabilities: prevQueryObject.availabilities.concat(name)
          };
        });
      } else {
        setQueryObject((prevQueryObject) => {
          return {
            ...prevQueryObject,
            availabilities: prevQueryObject.availabilities.filter(
              (e) => e !== name
            )
          };
        });
      }
      return;
    }
  }

  return (
    <div>
      <input
        type="checkbox"
        checked={queryObject.genders.includes("male")}
        onChange={handleChange}
        name="male"
      />
      <span>Male</span>
      <input
        type="checkbox"
        checked={queryObject.genders.includes("female")}
        onChange={handleChange}
        name="female"
      />
      <span>Female</span>
      <br />
      <input
        type="checkbox"
        checked={queryObject.availabilities.includes("available")}
        onChange={handleChange}
        name="available"
      />
      <span>Available</span>
      <input
        type="checkbox"
        checked={queryObject.availabilities.includes("not available")}
        onChange={handleChange}
        name="not available"
      />
      <span>Not available</span>
    </div>
  );
}

export default SideBar;

The problem is there in the approach of updating queryObject state .问题在于更新queryObject state 的方法。 Since queryObject state is an object and if we try to directly modify the object like this :-由于queryObject状态是一个对象,如果我们尝试像这样直接修改对象:-

    setQueryObject((prevQueryObject) => {
      prevQueryObject.genders.push(name);
      return prevQueryObject;
    });
  

React does not recognise any change in the state since the object has the same reference so it doesn't update DOM . React 无法识别状态的任何变化,因为对象具有相同的引用,因此它不会更新DOM Therefore we need to create a deep copy of that object and set it back to the object state again so that change in object state is recognised and React updates the DOM.因此,我们需要创建该对象的deep copy并将其再次设置回object state ,以便识别对象状态的变化并且 React 更新 DOM。

    setQueryObject((prevQueryObject) => {
      return{...prevQueryObject,genders:[...prevQueryObject.genders,name]};
    
    });
 

Full Working Code here - CodeSandbox Link完整的工作代码在这里 - CodeSandbox 链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM