>我正在尝试实现一个设置页面,其中我有一个全局设置和某种子设置(以滑块的形式(。
我无法设置从父级传递的初始值。
我正在处理以下情况:
1(当所有子设置都打开时,则父切换状态应打开状态
2(当任何子设置关闭时,父切换状态应切换到挂起
3(当所有子设置都关闭时,父母的开关状态应切换到关闭状态
4(同样在单击按钮时,我需要获取所有子组件的当前状态。
如果在 componentDidMount 内部添加 setState(可能是 API 调用会写在里面,这样开关的初始状态就会相应地设置然后能够改变(,子开关应该能够正确获取状态值,但这里没有。
而且我也看到切换以错误的方式发生。一旦您单击已选择的那个,它就会发生,这在理想情况下是错误的
尝试了以下方法,但似乎不起作用。为此,我正在为这个切换开关使用反应多切换。
有人可以在这里帮忙吗?
代码沙盒链接 : https://codesandbox.io/s/react-multi-toggle-solution-yn3fh
应用程序
import React from "react";
import ReactDOM from "react-dom";
import ChildSwitch from "./ChildSwitch";
import ParentSwitch from "./ParentSwitch";
import "./styles.css";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
parentVal: "disabled",
switch1Val: "disabled",
switch2Val: "disabled",
switch3Val: "disabled"
};
}
componentDidMount() {
this.setState({
switch1Val: "enabled",
switch2Val: "disabled",
switch3Val: "enabled"
});
}
onGetChildSwitchValues = () => {
console.log(this.state);
};
setChildSwitchValue = (whichSwitch, value) => {
this.setState(
prevState => Object.assign({}, prevState, { [whichSwitch]: value }),
this.setParentSwitchValue
);
};
setParentSwitchValue = () => {
const { switch1Val, switch2Val, switch3Val } = this.state;
const switchStates = [switch1Val, switch2Val, switch3Val];
const parent = switchStates.every(this.isEnabled)
? "enabled"
: switchStates.every(this.isDisabled)
? "disabled"
: "pending";
this.setState({ parentVal: parent });
};
isEnabled(value) {
return value === "enabled";
}
isDisabled(value) {
return value === "disabled";
}
render() {
const { parentVal, switch1Val, switch2Val, switch3Val } = this.state;
return (
<>
Parent Switch :{" "}
<ParentSwitch
parentSwitch={parentVal}
onSelect={this.setParentSwitchValue}
/>
Child Switches :
<ChildSwitch
childSwitch={switch1Val}
switchName={"switch1Val"}
onSelect={this.setChildSwitchValue}
/>
<ChildSwitch
childSwitch={switch2Val}
switchName={"switch2Val"}
onSelect={this.setChildSwitchValue}
/>
<ChildSwitch
childSwitch={switch3Val}
switchName={"switch3Val"}
onSelect={this.setChildSwitchValue}
/>
<button onClick={this.onGetChildSwitchValues}>Get Child Values</button>
</>
);
}
}
父母
import MultiToggle from "react-multi-toggle";
import React from "react";
import "react-multi-toggle/style.css";
class ParentSwitch extends React.Component {
constructor(props) {
super(props);
this.state = {
options: [
{
displayName: "Disabled",
value: "disabled",
optionClass: "red"
},
{
displayName: "Pending",
value: "pending",
optionClass: "grey"
},
{
displayName: "Enabled",
value: "enabled",
optionClass: "green"
}
]
};
}
render() {
const { options } = this.state;
return (
<MultiToggle
options={options}
selectedOption={this.props.parentSwitch}
onSelectOption={() => {}}
/>
);
}
}
export default ParentSwitch;
孩子
import MultiToggle from "react-multi-toggle";
import React from "react";
export default class ChildSwitch extends React.Component {
constructor(props) {
super(props);
this.state = {
options: [
{
displayName: "Disabled",
value: "disabled",
optionClass: "red"
},
{
displayName: "Enabled",
value: "enabled",
optionClass: "green"
}
],
selected: ""
};
}
componentDidMount() {
this.setState({ selected: this.props.childSwitch });
}
onSelectOption = selected => {
if (selected === "disabled") {
this.setState({ selected: "enabled" }, () =>
this.props.onSelect(this.props.switchName, "enabled")
);
} else {
this.setState({ selected: "disabled" }, () =>
this.props.onSelect(this.props.switchName, "disabled")
);
}
};
render() {
const { options, selected } = this.state;
return (
<MultiToggle
options={options}
selectedOption={selected}
onSelectOption={this.onSelectOption}
/>
);
}
}
解决此问题的一种方法是从主组件控制父开关和子开关。 查看工作分叉代码沙箱
.APP
import React from "react";
import ReactDOM from "react-dom";
import ChildSwitch from "./ChildSwitch";
import ParentSwitch from "./ParentSwitch";
import "./styles.css";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
parentVal: "disabled",
switch1Val: "enabled",
switch2Val: "disabled",
switch3Val: "enabled"
};
}
componentDidMount() {
this.setParentSwitchValue();
}
onGetChildSwitchValues = () => {
console.log(this.state);
};
setChildSwitchValue = (whichSwitch, selected) => {
this.setState(
prevState => ({ ...prevState, [whichSwitch]: selected }),
this.setParentSwitchValue
);
};
setParentSwitchValue = () => {
const { switch1Val, switch2Val, switch3Val } = this.state;
const switchStates = [switch1Val, switch2Val, switch3Val];
let parent = "pending";
if (switchStates.every(val => val === "enabled")) {
parent = "enabled";
}
if (switchStates.every(val => val === "disabled")) {
parent = "disabled";
}
this.setState(prevState => ({ ...prevState, parentVal: parent }));
};
render() {
const { parentVal, switch1Val, switch2Val, switch3Val } = this.state;
return (
<>
Parent Switch :{" "}
<ParentSwitch
parentSwitch={parentVal}
onSelect={this.setParentSwitchValue}
/>
Child Switches :
<ChildSwitch
switchName={"switch1Val"}
selected={switch1Val}
onSelect={this.setChildSwitchValue}
/>
<ChildSwitch
switchName={"switch2Val"}
selected={switch2Val}
onSelect={this.setChildSwitchValue}
/>
<ChildSwitch
switchName={"switch3Val"}
selected={switch3Val}
onSelect={this.setChildSwitchValue}
/>
<button onClick={this.onGetChildSwitchValues}>Get Child Values</button>
</>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
父母
import MultiToggle from "react-multi-toggle";
import React from "react";
import "react-multi-toggle/style.css";
class ParentSwitch extends React.Component {
constructor(props) {
super(props);
this.state = {
options: [
{
displayName: "Disabled",
value: "disabled",
optionClass: "red"
},
{
displayName: "Pending",
value: "pending",
optionClass: "grey"
},
{
displayName: "Enabled",
value: "enabled",
optionClass: "green"
}
]
};
}
render() {
const { options } = this.state;
return (
<MultiToggle
options={options}
selectedOption={this.props.parentSwitch}
onSelectOption={() => {}}
/>
);
}
}
export default ParentSwitch;
孩子
import MultiToggle from "react-multi-toggle";
import React from "react";
import "react-multi-toggle/style.css";
class ParentSwitch extends React.Component {
constructor(props) {
super(props);
this.state = {
options: [
{
displayName: "Disabled",
value: "disabled",
optionClass: "red"
},
{
displayName: "Pending",
value: "pending",
optionClass: "grey"
},
{
displayName: "Enabled",
value: "enabled",
optionClass: "green"
}
]
};
}
render() {
const { options } = this.state;
return (
<MultiToggle
options={options}
selectedOption={this.props.parentSwitch}
onSelectOption={() => {}}
/>
);
}
}
export default ParentSwitch;
问题是当childSwitch
属性更改时,您没有更新本地状态。因此,它将保持禁用状态。为此,您必须添加componentDidUpdate
方法或直接使用该属性而不使用任何本地状态。
在儿童交换机中
componentDidUpdate(prevProps) {
if(prevProps.childSwitch !== this.props.childSwitch) {
this.setState({ selected: this.props.childSwitch });
}
}
工作叉:https://codesandbox.io/s/react-multi-toggle-solution-8xnf3