我正在尝试实现一个设置页面,其中有一个全局设置和某种子设置(以滑块的形式)。
我无法设置从父级传递过来的首字母。
我正在处理以下情况:
1)当所有的孩子设置都打开时,则父母的开关状态应打开状态
2)当任何一个孩子设置关闭时,则应将父母切换状态切换为待处理状态
3)当所有的孩子设置都关闭时,则应将父母的开关状态切换到关闭状态
4)另外,在单击按钮时,我需要获取所有子组件的当前状态。
如果在parent的componentDidMount内添加setState(可能会在其中写入API调用,以便相应地设置开关的初始状态,然后可以进行更改),则子开关应该能够状态值是right,但是在这里不是。
我也看到切换是错误的。一旦您单击已经选择的错误的位置,就会发生这种情况
尝试了以下方法,但似乎不起作用。为此,我在此切换开关中使用了react-multi-toggle。
有人可以在这里帮忙吗?
代码沙箱链接: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}
/>
);
}
}
答案 0 :(得分:3)
解决此问题的一种方法是从主组件控制父开关和子开关。 检出working forked codesandbox
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;
答案 1 :(得分:1)
问题是childSwitch
属性更改时您没有更新本地状态。因此它将保持禁用状态。为此,您必须添加componentDidUpdate
方法或直接使用不带任何本地状态的属性。
在ChildSwitch中
componentDidUpdate(prevProps) {
if(prevProps.childSwitch !== this.props.childSwitch) {
this.setState({ selected: this.props.childSwitch });
}
}
工作叉:https://codesandbox.io/s/react-multi-toggle-solution-8xnf3