如何分别更新 array.map() 中元素的状态?
How to update state of elements from array.map() separately?
在我的代码中,我试图根据对象的背景数据检索背景图像,但是这些背景也会根据元素的状态而改变。
首先,我的数据数组如下所示:
const Cube = [
{
name: "foo"
faces: [
{
data: [
[{bonus: "bar", bg: "bar2"}],
...
],
...
},
...
],
...
},
...
];
这就是我的 App.js 的样子:
function App() {
const [cellState, setCellState] = useState("inactive");
return (
<div className="App">
<div id="cube-container">
{Cube[0].faces[0].data.map((row) => {
return row.map((cell, index) => {
return (
<img
src={require(`./assets/cube/Square_Cube_Icon/${cell.bg}${
cellState === "inactive" ? "_Unlit" : "_Partial"
}.png`)}
alt={`${cell.bg} background`}
className="cellItem"
onClick={() => setCellState("active")}
state={cellState}
key={index}
/>
);
});
})}
</div>
</div>
);
}
问题是,在 4x4 网格输出中,如果我点击任何项目,而不是因为状态变化而改变被点击元素的背景,它会改变每个单元格的背景,这应该发生,因为 useState 是所有单元格共享的他们中的。
我怎样才能使地图功能的每个元素都有自己的状态,我可以单独更新?
找到解决方案:
将其分离为组件并将键和单元格值作为道具传递,然后在内部创建和操纵状态修复 issue.Selected 答案也解决了问题。
这是为未来的读者准备的解决方案。
App.js
function App() {
return (
<div className="App">
<div id="cube-container">
{CubeOfTruth[0].faces[0].data.map((row) => {
return row.map((cell, index) => {
return <CubeItem key={index} cell={cell} />;
});
})}
</div>
</div>
);
}
CubeItem.js
function CubeItem({ cell, index }) {
const [cellState, setCellState] = useState("inactive");
return (
<img
src={require(`../assets/cube/Square_Cube_Icon/${cell.bg}${
cellState === "inactive" || cellState === "partial" ? "_Unlit" : ""
}.png`)}
alt={`${cell.bg} background`}
className="cellItem"
onClick={() => setCellState("active")}
state={cellState}
key={index}
/>
);
}
这是使用一个对象管理多个状态的简单方法,该对象的键代表您的单元格,值代表它是活动的还是非活动的。这也很容易概括,所以如果你添加更多的单元格,那么你所要做的就是将它添加到 initialState & 你的代码的其余部分应该按原样工作。
function App() {
// const [cellState, setCellState] = useState("inactive");
const initialState = {
bar1: "inactive",
bar2: "inactive",
bar3: "inactive",
bar4: "inactive",
}
const [cellState, SetCellState] = React.useState(initialState);
const handleSetCellState = (key) => {
setCellState({
...cellState,
[key]: "active",
});
};
return (
<div className="App">
<div id="cube-container">
{Cube[0].faces[0].data.map((row) => {
return row.map((cell, index) => {
return (
<img
src={require(`./assets/cube/Square_Cube_Icon/${cell.bg}${
cellState[cell.bg] === "inactive" ? "_Unlit" : "_Partial"
}.png`)}
alt={`${cell.bg} background`}
className="cellItem"
onClick={() => handleSetCellState(cell.bg)}
state={cellState[cell.bg]}
key={index}
/>
);
});
})}
</div>
</div>
);
}
在我的代码中,我试图根据对象的背景数据检索背景图像,但是这些背景也会根据元素的状态而改变。
首先,我的数据数组如下所示:
const Cube = [
{
name: "foo"
faces: [
{
data: [
[{bonus: "bar", bg: "bar2"}],
...
],
...
},
...
],
...
},
...
];
这就是我的 App.js 的样子:
function App() {
const [cellState, setCellState] = useState("inactive");
return (
<div className="App">
<div id="cube-container">
{Cube[0].faces[0].data.map((row) => {
return row.map((cell, index) => {
return (
<img
src={require(`./assets/cube/Square_Cube_Icon/${cell.bg}${
cellState === "inactive" ? "_Unlit" : "_Partial"
}.png`)}
alt={`${cell.bg} background`}
className="cellItem"
onClick={() => setCellState("active")}
state={cellState}
key={index}
/>
);
});
})}
</div>
</div>
);
}
问题是,在 4x4 网格输出中,如果我点击任何项目,而不是因为状态变化而改变被点击元素的背景,它会改变每个单元格的背景,这应该发生,因为 useState 是所有单元格共享的他们中的。 我怎样才能使地图功能的每个元素都有自己的状态,我可以单独更新?
找到解决方案:
将其分离为组件并将键和单元格值作为道具传递,然后在内部创建和操纵状态修复 issue.Selected 答案也解决了问题。
这是为未来的读者准备的解决方案。
App.js
function App() {
return (
<div className="App">
<div id="cube-container">
{CubeOfTruth[0].faces[0].data.map((row) => {
return row.map((cell, index) => {
return <CubeItem key={index} cell={cell} />;
});
})}
</div>
</div>
);
}
CubeItem.js
function CubeItem({ cell, index }) {
const [cellState, setCellState] = useState("inactive");
return (
<img
src={require(`../assets/cube/Square_Cube_Icon/${cell.bg}${
cellState === "inactive" || cellState === "partial" ? "_Unlit" : ""
}.png`)}
alt={`${cell.bg} background`}
className="cellItem"
onClick={() => setCellState("active")}
state={cellState}
key={index}
/>
);
}
这是使用一个对象管理多个状态的简单方法,该对象的键代表您的单元格,值代表它是活动的还是非活动的。这也很容易概括,所以如果你添加更多的单元格,那么你所要做的就是将它添加到 initialState & 你的代码的其余部分应该按原样工作。
function App() {
// const [cellState, setCellState] = useState("inactive");
const initialState = {
bar1: "inactive",
bar2: "inactive",
bar3: "inactive",
bar4: "inactive",
}
const [cellState, SetCellState] = React.useState(initialState);
const handleSetCellState = (key) => {
setCellState({
...cellState,
[key]: "active",
});
};
return (
<div className="App">
<div id="cube-container">
{Cube[0].faces[0].data.map((row) => {
return row.map((cell, index) => {
return (
<img
src={require(`./assets/cube/Square_Cube_Icon/${cell.bg}${
cellState[cell.bg] === "inactive" ? "_Unlit" : "_Partial"
}.png`)}
alt={`${cell.bg} background`}
className="cellItem"
onClick={() => handleSetCellState(cell.bg)}
state={cellState[cell.bg]}
key={index}
/>
);
});
})}
</div>
</div>
);
}