根据 objects 的数组形成组件
Forming the components based on the array of objects
对于应用程序的设置页面,我实现了一个启用(绿色)或禁用(红色)状态的滑块。而parent的设置是根据其children.
的值计算出来的
//Getting the switches configuration inside componnetDidMount something like this
var obj = [
{
parent_header_name: "parent1",
children_info: [
{
child_switch_name: "child1",
isEnabled: true
},
{
child_switch_name: "child2",
isEnabled: false
}
]
},
{
parent_header_name: "parent2",
children_info: [
{
child_switch_name: "child3",
isEnabled: true
}
]
},
{
parent_header_name: "parent3",
children_info: [
{
child_switch_name: "child4",
isEnabled: false
}
]
}
];
现在根据这个值,我需要形成一个 parent 和 children 的分组,如下所示:
Label(the value should be parent_header_name) : Parent Switch Component
Label for children(children_switch_name) : Child Switch Component
另外,在切换单个 children 开关时,我需要像这样获取该开关的信息:
例如,将 parent1 的 child1 改为残疾
[
{
parent_header_name: "parent1",
children_info: [
{
child_switch_name: "child1",
isEnabled: false
}
]
}
];
万一 parent1 启用,我需要获取它的所有子项值
[
{
parent_header_name: "parent1",
children_info: [
{
child_switch_name: "child1",
isEnabled: true
},
{
child_switch_name: "child2",
isEnabled: true
}
]
}
]
并且当 parents 开关被切换时(当 parent 启用时,children 将被启用,当禁用时 children 将被禁用;),我需要获取 parent
的全部信息
此外,我需要避免切换到 "partial" 状态,parent 应该只启用或禁用。 "Partial"只是代表性的
为此,我将 react-multi-toggle 用于此切换开关。
我试过这样的事情:https://codesandbox.io/s/parent-child-switches-gxfx6
我会这样做:
你有一个顶级 Settings
class 获取设置对象,将其保存为状态并映射数组,创建 ParentSwitch
个实例,传递完整的父设置,包括其子项和更新 Settings
状态的函数(例如,使用两个整数参数 - 父索引和子索引)作为 ParentSwitch
[= 的道具43=]
ParentSwitch
然后根据其 props 创建 ChildSwitch
es 并将通过其 props 获得的 updateSettings
函数传递给 ChildSwitch
当ChildSwitch
切换时,调用Settings
中的函数,切换Settings
的状态,传给ParentSwitch
以及显示的ChildSwitch
这样可以理解吗?有什么不清楚的地方欢迎提问
编辑:
这是工作代码笔。你必须自己布局,我已经花了足够多的时间在这上面。
https://codesandbox.io/s/parent-child-switches-jq0bp?fontsize=14
我所有的代码都在 Switches.js
您可以重构 Setting component
以允许它将您的开关 name and value according
呈现为从 API 接收到的数据。我建议您为每个 switches group
添加一个 id,这将简化您的工作。 Here is forked working sandbox。可以优化代码以适合您的用例。关键更改在 Setting Component
.
中完成
设置组件完整代码
import React, { Component, Fragment } from "react";
import isEqual from "lodash.isequal";
import ChildSwitch from "./ChildSwitch";
import ParentSwitch from "./ParentSwitch";
import { PARTIAL } from "./constant";
export default class Setting extends Component {
state = {
parent: {
value:
this.props.children.length > 1
? PARTIAL
: this.props.children[0].isEnabled
},
children: this.props.children
};
componentDidMount() {
this.setParentSwitchValue();
}
shouldComponentUpdate(nextProps, nextState) {
return !isEqual(this.state, nextState);
}
setChildSwitchValue = (id, isEnabled) => {
let clickedChild;
this.setState(
prevState => ({
...prevState,
children: prevState.children.map(child => {
if (child.id === id) {
clickedChild = { ...child, isEnabled: isEnabled };
return clickedChild;
} else {
return child;
}
})
}),
() => this.setParentSwitchValue(clickedChild)
);
};
setParentSwitchValue = clickedChild => {
const { children } = this.state;
let parentVal = PARTIAL;
if (children.every(({ isEnabled }) => isEnabled === true)) {
parentVal = true;
}
if (children.every(({ isEnabled }) => isEnabled === false)) {
parentVal = false;
}
this.setState(
prevState => ({
...prevState,
parent: {
value: parentVal
}
}),
() => {
this.handleChange();
if (clickedChild) {
const changed = {
parent: {
name: this.props.name,
value: parentVal
},
child: clickedChild
};
console.log("This is the changed child", changed);
}
}
);
};
setChildrenValue = value => {
this.setState(
prevState => ({
...prevState,
parent: {
value
},
children: prevState.children.map(child => ({
...child,
isEnabled: value
}))
}),
this.handleChange
);
};
handleChange = () => {
const { id, onChange } = this.props;
onChange(id, this.state);
};
handleParentClick = parentVal => {
if (parentVal !== PARTIAL) {
this.setChildrenValue(parentVal);
}
};
render() {
const { parent, children } = this.state;
const { name } = this.props;
return (
<div className="boxed">
<span>{name}</span>
<ParentSwitch
childrenCount={children.length}
parentSwitch={parent.value}
onSelect={this.handleParentClick}
/>
{children.map(({ id, name, isEnabled }) => (
<Fragment key={id}>
<span>{name}</span>
<ChildSwitch
switchName={id}
selected={isEnabled}
onSelect={this.setChildSwitchValue}
/>
</Fragment>
))}
</div>
);
}
}
对于应用程序的设置页面,我实现了一个启用(绿色)或禁用(红色)状态的滑块。而parent的设置是根据其children.
的值计算出来的//Getting the switches configuration inside componnetDidMount something like this
var obj = [
{
parent_header_name: "parent1",
children_info: [
{
child_switch_name: "child1",
isEnabled: true
},
{
child_switch_name: "child2",
isEnabled: false
}
]
},
{
parent_header_name: "parent2",
children_info: [
{
child_switch_name: "child3",
isEnabled: true
}
]
},
{
parent_header_name: "parent3",
children_info: [
{
child_switch_name: "child4",
isEnabled: false
}
]
}
];
现在根据这个值,我需要形成一个 parent 和 children 的分组,如下所示:
Label(the value should be parent_header_name) : Parent Switch Component
Label for children(children_switch_name) : Child Switch Component
另外,在切换单个 children 开关时,我需要像这样获取该开关的信息:
例如,将 parent1 的 child1 改为残疾
[
{
parent_header_name: "parent1",
children_info: [
{
child_switch_name: "child1",
isEnabled: false
}
]
}
];
万一 parent1 启用,我需要获取它的所有子项值
[
{
parent_header_name: "parent1",
children_info: [
{
child_switch_name: "child1",
isEnabled: true
},
{
child_switch_name: "child2",
isEnabled: true
}
]
}
]
并且当 parents 开关被切换时(当 parent 启用时,children 将被启用,当禁用时 children 将被禁用;),我需要获取 parent
的全部信息此外,我需要避免切换到 "partial" 状态,parent 应该只启用或禁用。 "Partial"只是代表性的
为此,我将 react-multi-toggle 用于此切换开关。
我试过这样的事情:https://codesandbox.io/s/parent-child-switches-gxfx6
我会这样做:
你有一个顶级
[= 的道具43=]Settings
class 获取设置对象,将其保存为状态并映射数组,创建ParentSwitch
个实例,传递完整的父设置,包括其子项和更新Settings
状态的函数(例如,使用两个整数参数 - 父索引和子索引)作为ParentSwitch
ParentSwitch
然后根据其 props 创建ChildSwitch
es 并将通过其 props 获得的updateSettings
函数传递给ChildSwitch
当
ChildSwitch
切换时,调用Settings
中的函数,切换Settings
的状态,传给ParentSwitch
以及显示的ChildSwitch
这样可以理解吗?有什么不清楚的地方欢迎提问
编辑:
这是工作代码笔。你必须自己布局,我已经花了足够多的时间在这上面。
https://codesandbox.io/s/parent-child-switches-jq0bp?fontsize=14
我所有的代码都在 Switches.js
您可以重构 Setting component
以允许它将您的开关 name and value according
呈现为从 API 接收到的数据。我建议您为每个 switches group
添加一个 id,这将简化您的工作。 Here is forked working sandbox。可以优化代码以适合您的用例。关键更改在 Setting Component
.
设置组件完整代码
import React, { Component, Fragment } from "react";
import isEqual from "lodash.isequal";
import ChildSwitch from "./ChildSwitch";
import ParentSwitch from "./ParentSwitch";
import { PARTIAL } from "./constant";
export default class Setting extends Component {
state = {
parent: {
value:
this.props.children.length > 1
? PARTIAL
: this.props.children[0].isEnabled
},
children: this.props.children
};
componentDidMount() {
this.setParentSwitchValue();
}
shouldComponentUpdate(nextProps, nextState) {
return !isEqual(this.state, nextState);
}
setChildSwitchValue = (id, isEnabled) => {
let clickedChild;
this.setState(
prevState => ({
...prevState,
children: prevState.children.map(child => {
if (child.id === id) {
clickedChild = { ...child, isEnabled: isEnabled };
return clickedChild;
} else {
return child;
}
})
}),
() => this.setParentSwitchValue(clickedChild)
);
};
setParentSwitchValue = clickedChild => {
const { children } = this.state;
let parentVal = PARTIAL;
if (children.every(({ isEnabled }) => isEnabled === true)) {
parentVal = true;
}
if (children.every(({ isEnabled }) => isEnabled === false)) {
parentVal = false;
}
this.setState(
prevState => ({
...prevState,
parent: {
value: parentVal
}
}),
() => {
this.handleChange();
if (clickedChild) {
const changed = {
parent: {
name: this.props.name,
value: parentVal
},
child: clickedChild
};
console.log("This is the changed child", changed);
}
}
);
};
setChildrenValue = value => {
this.setState(
prevState => ({
...prevState,
parent: {
value
},
children: prevState.children.map(child => ({
...child,
isEnabled: value
}))
}),
this.handleChange
);
};
handleChange = () => {
const { id, onChange } = this.props;
onChange(id, this.state);
};
handleParentClick = parentVal => {
if (parentVal !== PARTIAL) {
this.setChildrenValue(parentVal);
}
};
render() {
const { parent, children } = this.state;
const { name } = this.props;
return (
<div className="boxed">
<span>{name}</span>
<ParentSwitch
childrenCount={children.length}
parentSwitch={parent.value}
onSelect={this.handleParentClick}
/>
{children.map(({ id, name, isEnabled }) => (
<Fragment key={id}>
<span>{name}</span>
<ChildSwitch
switchName={id}
selected={isEnabled}
onSelect={this.setChildSwitchValue}
/>
</Fragment>
))}
</div>
);
}
}