我做了一个PoC,以查看如何在复选框的动态列表上处理我的更改检测(请注意,我事先不知道我有多少复选框。)我创建了一个ES6映射(字典),该映射跟踪的已检查状态每个复选框。但由于某种原因,我收到以下错误:
A component is changing an uncontrolled input of type checkbox to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component
通常,当我知道表单输入字段的数量时,我会通过状态进行跟踪,但是如何处理这种情况。逻辑工作正常,但我需要摆脱错误。
我的应用代码:
import React, { Component } from "react";
import Checkbox from "./checkbox";
class App extends Component {
constructor(props) {
super(props);
this.state = {
checkedItems: new Map()
};
this.handleChange = this.handleChange.bind(this);
}
handleChange = e => {
const item = e.target.name;
const isChecked = e.target.checked;
this.setState(prevState => ({
checkedItems: prevState.checkedItems.set(item, isChecked)
}));
};
deleteCheckboxState = (name, checked) => {
const updateChecked = typeof checked === "undefined" ? true : false;
this.setState(prevState => prevState.checkedItems.set(name, updateChecked));
};
clearAllCheckboxes = () => {
const clearCheckedItems = new Map();
this.setState({ checkedItems: clearCheckedItems });
};
render() {
const checkboxes = [
{
name: "check-box-1",
key: "checkBox1",
label: "Check Box 1"
},
{
name: "check-box-2",
key: "checkBox2",
label: "Check Box 2"
},
{
name: "check-box-3",
key: "checkBox3",
label: "Check Box 3"
},
{
name: "check-box-4",
key: "checkBox4",
label: "Check Box 4"
}
];
const checkboxesToRender = checkboxes.map(item => {
return (
<label key={item.key}>
{item.name}
<Checkbox
name={item.name}
checked={this.state.checkedItems.get(item.name)}
onChange={this.handleChange}
type="checkbox"
/>
</label>
);
});
const checkboxesDeleteHandlers = checkboxes.map(item => {
return (
<span
key={item.name}
onClick={() =>
this.deleteCheckboxState(
item.name,
this.state.checkedItems.get(item.name)
)
}
>
{item.name}
</span>
);
});
return (
<div className="App">
{checkboxesToRender}
<br /> {checkboxesDeleteHandlers}
<p onClick={this.clearAllCheckboxes}>clear all</p>
</div>
);
}
}
export default App;
复选框可重用组件:
import React from "react";
class Checkbox extends React.Component {
render() {
return (
<input
type={this.props.type}
name={this.props.name}
checked={this.props.checked}
onChange={this.props.onChange}
/>
);
}
}
export default Checkbox;
答案 0 :(得分:2)
问题是检查状态最初是undefined
,这是一个伪造的值,但被解释为未提供。
因此,您可以使用!!
来确保虚假状态实际上是假的。
所以换行
checked={this.state.checkedItems.get(item.name)}
对此
checked={!!this.state.checkedItems.get(item.name)}
答案 1 :(得分:0)
React会向您发出此警告,因为它就像您在受控组件和非受控组件之间进行选择一样。
对于复选框输入,如果未定义其检查的道具,则组件被视为受控制的。
我刚刚给了checked一个默认值,并将代码测试更改为undefined。
警告应该消失了。
// import React, { Component } from "react";
class Checkbox extends React.Component {
static defaultProps = {
checked: false
}
render() {
return (
<input
type={this.props.type}
name={this.props.name}
checked={this.props.checked}
onChange={this.props.onChange}
/>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
checkedItems: new Map()
};
this.handleChange = this.handleChange.bind(this);
}
handleChange = e => {
const item = e.target.name;
const isChecked = e.target.checked;
this.setState(prevState => ({
checkedItems: prevState.checkedItems.set(item, isChecked)
}));
};
deleteCheckboxState = (name, checked) => {
const updateChecked = checked == null ? true : false;
this.setState(prevState => prevState.checkedItems.set(name, updateChecked));
};
clearAllCheckboxes = () => {
const clearCheckedItems = new Map();
this.setState({ checkedItems: clearCheckedItems });
};
render() {
const checkboxes = [
{
name: "check-box-1",
key: "checkBox1",
label: "Check Box 1"
},
{
name: "check-box-2",
key: "checkBox2",
label: "Check Box 2"
},
{
name: "check-box-3",
key: "checkBox3",
label: "Check Box 3"
},
{
name: "check-box-4",
key: "checkBox4",
label: "Check Box 4"
}
];
const checkboxesToRender = checkboxes.map(item => {
return (
<label key={item.key}>
{item.name}
<Checkbox
name={item.name}
checked={this.state.checkedItems.get(item.name) || false}
onChange={this.handleChange}
type="checkbox"
/>
</label>
);
});
const checkboxesDeleteHandlers = checkboxes.map(item => {
return (
<span
key={item.name}
onClick={() =>
this.deleteCheckboxState(
item.name,
this.state.checkedItems.get(item.name)
)
}
>
{item.name}
</span>
);
});
return (
<div className="App">
{checkboxesToRender}
<br /> {checkboxesDeleteHandlers}
<p onClick={this.clearAllCheckboxes}>clear all</p>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>