我有一个从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>
);
});
}
谢谢。
答案 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说,“嘿,这与我以前的状态相同,我不需要做任何事情。”