在usestate挂钩中更新状态后,React不会更改状态(以自定义函数形式)

时间:2019-10-15 17:34:44

标签: javascript reactjs react-hooks

我在react 16.10.2中使用usestate挂钩,但是在usetate挂钩中使用自定义函数更新初始状态后,react不会触发重新渲染(未渲染OtherComponent),这是我的react组件:

import React, { useState, useEffect } from 'react';
import OtherComponent from "./OtherComponent";

function Component(props) {

   const [render, setRender] = useState({0:false, 1:false});
   const display_data = (index) => {
      setRender((prevState) => {
         prevState[index] = !prevState[index];
         return prevState;
      });
   };

   return (
      <>
         {{custom_json_array}.map((record, index) => {
            return (
                  <div>{teacher_render[index] ? 'true' : 'false'}</div>
                  <button onClick={() => display_data(index)}>change state</button>
                  {render[index] ? <OtherComponent /> : ''}
               </div>)
         })}
      </>
   );

}

但是奇怪的是,如果我从钩子更新器函数返回{... prevState},一切正常,并且触发了重新渲染! 我完全感到困惑,为什么反应会表现得如此?!

2 个答案:

答案 0 :(得分:2)

我认为问题是您正在突变render

<button 
  onClick={() => setRender({ ...render, [index]: !render[index] })}
>
  change state
</button>

在此示例中,单击名称以查看自定义组件,然后再次单击以隐藏

https://codesandbox.io/s/dark-wind-3310q

const CustomComponent = () => (
  <div style={{ marginLeft: 10, background: "red" }}>I'm Selected!</div>
);

function App() {
  const [people] = useState([
    { id: 0, name: "Mario" },
    { id: 1, name: "Luigi" },
    { id: 2, name: "Peach" }
  ]);

  const [selected, setSelected] = useState({});

  return (
    <div>
      {people.map(({ id, name }) => (
        <div
          style={{ display: "flex", cursor: "pointer" }}
          key={id}
          onClick={() => setSelected({ ...selected, [id]: !selected[id] })}
        >
          {name}
          {selected[id] && <CustomComponent />}
        </div>
      ))}
    </div>
  );
}

这是您发布的错误代码的简化示例,以显示没有更新发生:

https://codesandbox.io/s/goofy-williamson-22fgs

function App() {
  const [obj, setObj] = useState({ name: "Mario" });
  const change = () => {
    // The following commented code will display no change
    // obj.name = "Peach";
    // setObj(obj);
    setObj({ ...obj, name: "Peach" });
  };
  return (
    <div className="App">
      <div>{obj.name}</div>
      <button onClick={change}>Change!</button>
    </div>
  );
}

答案 1 :(得分:0)

您的onclick处理程序在标记中称为display_teacher_data,但在组件中称为display_data。将它们设置为相同,以便状态更改。