尝试创建一个受控的切换器按钮
Trying to create a controlled switcher button
我在网上找到了这段代码(它在 google 结果中排名靠前):
https://codepen.io/BuiltByEdgar/pen/jWOVYQ
但我对它的代码感到厌烦。
我正在尝试将这些按钮设置为默认状态为开启状态,不允许同时关闭两个按钮。我为此选择的 UI 行为是简单地重新启用另一个,如果它的兄弟姐妹被关闭:
onONEClick() {
let {
TWO,
ONE,
} = this.state;
if (TWO) {
ONE = !ONE;
} else if (ONE) {
TWO = !TWO;
ONE = !TWO;
} else {
ONE = !ONE;
}
this.setState({
ONE,
TWO,
});
this.props.callBack({
ONE,
TWO,
});
}
onTWOClick() {
let {
TWO,
ONE,
} = this.state;
if (ONE) {
TWO = !TWO;
} else if (TWO) {
TWO = !TWO;
ONE = !ONE;
} else {
TWO = !TWO;
}
this.setState({
ONE,
TWO,
});
this.props.callBack({
ONE,
TWO,
});
}
和渲染:
<div>
<div className="switch-container">
<label>
<input
onChange={this.onONEClick}
type="checkbox"
className="switch"
value={this.state.ONE}
checked={this.state.ONE}
/>
<div>
<span><g className="icon icon-toolbar grid-view" /></span>
<span><g className="icon icon-toolbar ticket-view" /></span>
<div />
</div>
</label>
</div>
ONE
</div>
<div>
<div className="switch-container">
<label>
<input
onChange={this.onTWOClick}
type="checkbox"
className="switch"
value={this.state.TWO}
checked={this.state.TWO}
/>
<div>
<span><g className="icon icon-toolbar grid-view" /></span>
<span><g className="icon icon-toolbar ticket-view" /></span>
<div />
</div>
</label>
</div>
TWO
</div>
够简单了吧?
问题是反应讨厌我的切换器是 "checkbox" 类型的输入:
如您所见,我已尽最大努力避免这种情况发生,但我认为除了人工之外,不可能拥有输入类型并更改其检查状态。
所以我在想也许我可以通过仅使用 div 重建复选框来解决问题。 (label标签也违反了ESLint)
JLAITIO 回答:
这是我添加的内容(文件的顶部带有 props 声明和构造函数):
const propTypes = {
value: React.PropTypes.object,
type: React.PropTypes.string,
callBack: React.PropTypes.func,
ONE: React.PropTypes.bool,
TWO: React.PropTypes.bool,
};
const defaultProps = {
callBack: () => {},
onChange: () => {
},
value: { type: '' },
ONE: true,
TWO: true,
};
class ProviderInfosComponent extends Component {
constructor(props) {
super(props);
const initialValue = props.value;
this.state = {
...initialValue,
ONE: this.props.ONE,
TWO: this.props.TWO,
};
this.onONEClick = this.onONEClick.bind(this);
this.onTWOClick = this.onTWOClick.bind(this);
}
如果在 any 点你的 value
属性没有设置,或者设置为 undefined
的值,然后随后它是一个现有的 React 状态值。
我最好的猜测是您的构造函数没有初始化 ONE
和 TWO
,因此开始时的值为 undefined
。然后,当您实际拥有一个值时,该组件从不受控制的 (="component state independent of React") 转移到受控的 (="component state tied directly to React state").
作为对@jlaitio 回答的补充,
您不必为复选框输入设置值。您可以只使用组件的 checked 道具。此外,对更改后的函数进行小幅改进可能有助于更轻松地跟进这些值。
constructor(props) {
super(props);
this.state = {
ONE: true,
TWO: true
};
}
onONEChange = (event) => {
this.setState((prevState) => {
ONE: event.target.checked,
TWO: (event.target.checked === false ? true : prevState.TWO) // change state of TWO if ONE is false else just leave it as is
}, () => {
this.props.callBack({ ONE: this.state.ONE, TWO: this.state.TWO });
});
}
onTWOChange = (event) => {
this.setState((prevState) => {
ONE: (event.target.checked === false ? true : prevState.ONE), // change state of ONE if TWO is false else just leave it as is
TWO: event.target.checked
}, () => {
this.props.callBack({ ONE: this.state.ONE, TWO: this.state.TWO });
});
}
我在网上找到了这段代码(它在 google 结果中排名靠前): https://codepen.io/BuiltByEdgar/pen/jWOVYQ
但我对它的代码感到厌烦。
我正在尝试将这些按钮设置为默认状态为开启状态,不允许同时关闭两个按钮。我为此选择的 UI 行为是简单地重新启用另一个,如果它的兄弟姐妹被关闭:
onONEClick() {
let {
TWO,
ONE,
} = this.state;
if (TWO) {
ONE = !ONE;
} else if (ONE) {
TWO = !TWO;
ONE = !TWO;
} else {
ONE = !ONE;
}
this.setState({
ONE,
TWO,
});
this.props.callBack({
ONE,
TWO,
});
}
onTWOClick() {
let {
TWO,
ONE,
} = this.state;
if (ONE) {
TWO = !TWO;
} else if (TWO) {
TWO = !TWO;
ONE = !ONE;
} else {
TWO = !TWO;
}
this.setState({
ONE,
TWO,
});
this.props.callBack({
ONE,
TWO,
});
}
和渲染:
<div>
<div className="switch-container">
<label>
<input
onChange={this.onONEClick}
type="checkbox"
className="switch"
value={this.state.ONE}
checked={this.state.ONE}
/>
<div>
<span><g className="icon icon-toolbar grid-view" /></span>
<span><g className="icon icon-toolbar ticket-view" /></span>
<div />
</div>
</label>
</div>
ONE
</div>
<div>
<div className="switch-container">
<label>
<input
onChange={this.onTWOClick}
type="checkbox"
className="switch"
value={this.state.TWO}
checked={this.state.TWO}
/>
<div>
<span><g className="icon icon-toolbar grid-view" /></span>
<span><g className="icon icon-toolbar ticket-view" /></span>
<div />
</div>
</label>
</div>
TWO
</div>
够简单了吧?
问题是反应讨厌我的切换器是 "checkbox" 类型的输入:
如您所见,我已尽最大努力避免这种情况发生,但我认为除了人工之外,不可能拥有输入类型并更改其检查状态。
所以我在想也许我可以通过仅使用 div 重建复选框来解决问题。 (label标签也违反了ESLint)
JLAITIO 回答:
这是我添加的内容(文件的顶部带有 props 声明和构造函数):
const propTypes = {
value: React.PropTypes.object,
type: React.PropTypes.string,
callBack: React.PropTypes.func,
ONE: React.PropTypes.bool,
TWO: React.PropTypes.bool,
};
const defaultProps = {
callBack: () => {},
onChange: () => {
},
value: { type: '' },
ONE: true,
TWO: true,
};
class ProviderInfosComponent extends Component {
constructor(props) {
super(props);
const initialValue = props.value;
this.state = {
...initialValue,
ONE: this.props.ONE,
TWO: this.props.TWO,
};
this.onONEClick = this.onONEClick.bind(this);
this.onTWOClick = this.onTWOClick.bind(this);
}
如果在 any 点你的 value
属性没有设置,或者设置为 undefined
的值,然后随后它是一个现有的 React 状态值。
我最好的猜测是您的构造函数没有初始化 ONE
和 TWO
,因此开始时的值为 undefined
。然后,当您实际拥有一个值时,该组件从不受控制的 (="component state independent of React") 转移到受控的 (="component state tied directly to React state").
作为对@jlaitio 回答的补充,
您不必为复选框输入设置值。您可以只使用组件的 checked 道具。此外,对更改后的函数进行小幅改进可能有助于更轻松地跟进这些值。
constructor(props) {
super(props);
this.state = {
ONE: true,
TWO: true
};
}
onONEChange = (event) => {
this.setState((prevState) => {
ONE: event.target.checked,
TWO: (event.target.checked === false ? true : prevState.TWO) // change state of TWO if ONE is false else just leave it as is
}, () => {
this.props.callBack({ ONE: this.state.ONE, TWO: this.state.TWO });
});
}
onTWOChange = (event) => {
this.setState((prevState) => {
ONE: (event.target.checked === false ? true : prevState.ONE), // change state of ONE if TWO is false else just leave it as is
TWO: event.target.checked
}, () => {
this.props.callBack({ ONE: this.state.ONE, TWO: this.state.TWO });
});
}