我正在尝试创建一个嵌套/分组复选框的列表,在其中选择一个复选框(父级)应基于数据对象数组选择其他复选框(所有子级)。现在,以checked
状态对App.js
值进行硬编码会反映复选框的输出滴答声,但是当通过将setState
作为道具传递给子组件来修改状态时,复选框不更新。
一种部分解决我想做的事情的怪诞方法是通过在useState
的onChange方法中使用CheckBoxGroup.js
来更改布尔值,从而迫使组件进行更新。但是即使那样,控制台仍会显示正确的更改的props.state,但是app.js组件的状态不会反映出来。没有useState,复选框似乎也不会重新呈现。有人可以帮忙吗?
谢谢
以下是代码。 此处的代码沙箱链接:https://codesandbox.io/s/red-haze-ij1km?fontsize=14&hidenavigation=1&theme=dark
App.js
import React, { useState } from "react";
import "./styles.css";
import FoodGroup from "./FoodGroup";
export default function App() {
let arr = [
{
name: "Fruits",
parentId: 100,
data: [{ value: "Apple", id: 1 }, { value: "Banana", id: 2 }]
},
{
name: "Vegetables",
parentId: 200,
data: [{ value: "Potato", id: 3 }, { value: "Onion", id: 4 }]
}
];
const [state, setState] = useState({
// basically selecting all id : { selected : true } for parent id and child id
1: { selected: false },
2: { selected: false },
100: { selected: false }
});
return (
<div className="App">
<FoodGroup data={arr} state={state} setState={setState} />
</div>
);
}
FoodGroup.js
import React from "react";
import CheckBoxGroup from "./CheckBoxGroup";
const FoodGroup = props => {
let groups = props.data.map((group, index) => (
<CheckBoxGroup
group={group}
key={index}
data={props.data}
setState={props.setState}
state={props.state}
/>
));
return <ul>{groups}</ul>;
};
export default FoodGroup;
CheckBoxGroup.js
import React, { useState } from "react";
import CheckBox from "./CheckBox";
const CheckBoxGroup = props => {
// const [a, b] = useState(false);
const onChildChange = (child, e) => {
let childSelected = props.state;
if (!childSelected[child]) {
childSelected[child] = {};
}
childSelected[child].selected = e.target.checked;
props.setState(childSelected);
// b(!a); a hacky way I found a work around to force re render the component otherwise it doesn't
// work
};
const onParentChange = (child, e) => {
let childSelected = props.state;
if (!childSelected[child]) {
childSelected[child] = {};
}
let childInThatParent = [];
props.data.forEach(group => {
if (group.parentId === child) {
group.data.forEach(item => {
childInThatParent.push(item.id);
});
}
});
childSelected[child].selected = e.target.checked;
childInThatParent.forEach(child => {
if (!childSelected[child]) {
childSelected[child] = {};
}
childSelected[child].selected = e.target.checked;
});
props.setState(childSelected);
// b(!a);
};
let checkboxes = props.group.data.map((item, index) => (
<CheckBox
onChange={onChildChange}
value={item.value}
id={item.id}
key={item.id}
setState={props.setState}
state={props.state}
/>
));
return (
<React.Fragment>
<CheckBox
onChange={onParentChange}
value={props.group.name}
id={props.group.parentId}
countrySelected={props.state}
setState={props.setState}
state={props.state}
/>
<ul>{checkboxes}</ul>
</React.Fragment>
);
};
export default CheckBoxGroup;
CheckBox.js
import React, { useState } from "react";
const CheckBox = ({ state, id, onChange, value }) => {
return (
<li>
<input
type="checkbox"
value={id}
onChange={e => {
onChange(id, e);
}}
checked={state[id].selected}
/>
{value}
</li>
);
};
export default CheckBox;
答案 0 :(得分:1)
在用onChildChange
和onParentChange
方法更新状态时,您引用的是同一状态。您可以检查沙箱进行修复:https://codesandbox.io/s/loving-moon-0e91c
检查CheckBoxGroup.js文件中的onChildChange
和onParentChange
方法