状态更改时,React不会重新渲染

时间:2020-01-03 18:25:46

标签: javascript reactjs

我有一个从API调用中提取的仓库清单。然后,我呈现了一个组件列表,这些组件为每个仓库提供了复选框。我将复选框的状态保留在一个对象中(使用useState挂钩)。选中/取消选中该复选框时,将相应地更新对象。

我的任务是在未选中时在复选框上方显示一条消息。我尝试仅使用对象,但是,当对象更改时,组件未重新渲染。

我通过简单地添加另一个useState挂钩(布尔值)作为切换找到了解决方案。添加后,该组件将重新渲染,并且将读取我对象的值并对其进行适当的操作。

我的问题是:为什么我必须添加切换开关才能使React重新渲染组件?我是否以允许React查看状态变化的方式更新对象?有人可以告诉我这是怎么回事吗?

我创建了一个沙箱来演示此问题:https://codesandbox.io/s/intelligent-bhabha-lk61n

function App() {
  const warehouses = [
    {
      warehouseId: "CHI"
    },
    {
      warehouseId: "DAL"
    },
    {
      warehouseId: "MIA"
    }
  ];

  const [warehouseStatus, setWarehouseStatus] = useState({});
  const [toggle, setToggle] = useState(true);

  useEffect(() => {
    if (warehouses.length > 0) {
      const warehouseStates = warehouses.reduce((acc, item) => {
        acc[item.warehouseId] = true;
        return acc;
      }, {});
      setWarehouseStatus(warehouseStates);
    }
  }, [warehouses.length]);

  const handleChange = obj => {
    const newState = warehouseStatus;
    const { name, value } = obj;
    newState[name] = value;
    setWarehouseStatus(newState);
    setToggle(!toggle);
  };

  return warehouses.map((wh, idx) => {
    return (
      <div key={idx}>
        {!warehouseStatus[wh.warehouseId] && <span>This is whack</span>}
        <MyCheckbox
          initialState
          id={wh.warehouseId}
          onCheckChanged={handleChange}
          label={wh.warehouseId}
        />
      </div>
    );
  });
}

谢谢。

1 个答案:

答案 0 :(得分:2)

您正在改变状态(don't mutate state

此:

  const handleChange = obj => {
    const newState = warehouseStatus;
    const { name, value } = obj;
    newState[name] = value;
    setWarehouseStatus(newState);
  };

应为:

  const handleChange = ({name,value}) => {
    setWarehouseStatus({...warehouseStatus,[name]:value});
  };

看到问题了吗?

    const newState = warehouseStatus; <- this isn't "newState", it's a reference to the existing state
    const { name, value } = obj;
    newState[name] = value; <- and now you've gone and mutated the existing state

然后,您使用相同的状态引用(直接变异)调用setState。 React说,“嘿,这与我以前的状态相同,我不需要做任何事情。”