如何使用 redux \ redux-form 初始化独立的 Radio Button Group 组件 checked 属性 state
How to initialize standalone Radio Button Group component checked property state with redux \ redux-form
我正在学习 React,但被卡住了。我正在尝试在编辑和创建组件之间共享一个表单。我真的很难弄清楚我在为无线电组初始化选中 属性 的值时做错了什么。页面加载后,我可以切换单选按钮。然而,最初两者都没有被检查。
我开始觉得我在表格上设置的 属性 不正确。
编辑组件(形成父组件):
class CompanyMasterEdit extends React.Component {
componentDidMount() {this.props.fetchCompany(this.props.match.params.companyId,this.props.match.params.companyName)}
onSubmit = (formValues) => { this.props.editCompany(this.props.match.params.companyId, formValues) }
render() {
return (
<div style={{ padding: 50 }}>
<h1 style={{ textAlign: "center" }}>Edit Company Master Record</h1>
<h5 style={{ textAlign: "center" }}>
<span style={{ color: "red" }}>*</span> indicates required field
</h5>
<CompanyMasterForm
initialValues={_.pick(
this.props.company,
"isKeyCompany",...
)}
onSubmit={this.onSubmit}
/>
const mapStateToProps = (state, ownProps) => {
return { company: state.companies[ownProps.match.params.companyId] }
}
export default connect(mapStateToProps, { fetchCompany, editCompany })( CompanyMasterEdit)
形式:
class CompanyMasterForm extends React.Component {
<form
className="ui form error"
onSubmit={this.props.handleSubmit(this.onSubmit)}
>
<Field
label="Is This a Key Company?"
component={RadioGroup}
name="isKeyCompany"
required={true}
options={[
{ title: "Yes", value: true },
{ title: "No", value: false },
]}
checked={this.props.initialValues.isKeyCompany}
// onClick={this.setIsKeyCompany}
//onClick={(e) => this.setState({ isKeyCompany: e.target.checked })}
onClick={() => {this.setState((prevState) => {return {checked: !this.props.initialValues.isKeyCompany,}})
}}
/>
<button className="ui button primary">Submit</button>
</form>
RadioButtonGroup 作为单独的组件:
class RadioGroup extends React.Component {
render() {
return (
<div className={className}>
<div className="inline fields">
<div className={labelClassName}>
<label>{label}</label>
</div>
{options.map((o) => {
const isChecked = o.value ? "true" : "false"
console.log("o.value :", o.value)
return (
<label key={o.title}>
<input
type="radio"
{...input}
value={o.value}
checked={isChecked === input.value}
/>
{o.title}
</label>
)
})}
</div>
</div>
)
}
}
// const mapStateToProps = (state) => {
// console.log("radio group state : ", state)
// return { isKeyCompany: state.form.companyMasterForm.values.isKeyCompany }
// }
// export default connect(mapStateToProps)(RadioGroup)
// export default connect(null)(RadioGroup)
export default RadioGroup
我有一个codesandbox了。我觉得我离它很近,在它周围跳舞,但我无法得到它。感谢任何帮助。
选项的值为文本(input.value 是文本,但 o.value 是布尔值)。检查的 属性 是布尔值。 ===
是 never going to be quite right,除非你解决其中一个问题。
此更改会显示一个选项。并不是说它真的是正确的改变。我们可能应该对选中的 属性.
进行稍微更稳健的比较
checked={o.value == input.value}
它目前是布尔值,因为你在这里设置了它
options={[
{ title: "Yes", value: true },
{ title: "No", value: false },
]}
+1 来自@Nikki9696 的研究,但更好的解决方案是使用严格的 ===
检查并更改选项配置以具有字符串值:
options={[
{ title: "Yes", value: 'true' },
{ title: "No", value: 'false' },
]}
那是因为 "true" != true
(字符串值“true”不等于布尔值 true
,即使有类型强制)。 "false"
和 false
之间的比较也是如此。
几点说明:
- 互斥的单选按钮应该有相同的
name
属性。所以我们可以只为一组选项写一个硬编码字符串。
-
value
属性不决定单选按钮是否激活。这是通过 checked
/defaultChecked
完成的。如果我们有两个以上的选项(标记每个选项),value
属性特别有用。
- 上一个代码示例中变量
input
的作用不是很清楚?
- 如果只有两个可能的值,最好避免将
"true"
和 "false"
作为字符串值。在这种情况下,布尔值(true
或 false
不带引号)更合适。这是表示状态的最简单方法,"True"
等拼写错误不会漏掉(当您使用字符串时,此类拼写错误将不会被注意到)。
- 如果您使用 uncontrolled components(即输入的值未保存在组件的状态中),您应该使用
defaultChecked
而不是 checked
,如果您愿意的话用户能够在页面加载后切换复选框。
- 如果您想在应用的其他地方重复使用复选框的状态,则必须使用 controlled components。在这种情况下,设置状态也应该略有不同(见下文)。
编辑:一些补充说明以回应您在下方的评论。
(您提供的代码原样包含语法错误,如果代码正确且尽可能少(且格式正确),则更容易提供帮助。)
- 你不应该设置你的状态
onSubmit
(在表单元素上),就像你在这里所做的那样。更改应设置为 onChange
(在输入元素上),因为输入元素的状态 是 您应用程序的相应状态,因此它们必须始终同步。
- 实际上设置状态的函数似乎是
editCompany
reducer。因此,您应该通过将其从父组件向下传递(丑陋)或通过将输入组件连接到 Redux 存储(清洁器)来使其对 input
元素可用。
class CompanyMasterEdit extends React.Component {
componentDidMount() {
const { fetchCompany, match } = this.props;
fetchCompany(match.params.companyId, match.params.companyName);
}
render() {
const { company } = this.props;
return (
<div style={{ padding: 50 }}>
<h1 style={{ textAlign: "center" }}>Edit Company Master Record</h1>
<h5 style={{ textAlign: "center" }}>
<span style={{ color: "red" }}>*</span> indicates required field
</h5>
<CompanyMasterForm initialValues={_.pick(company, "isKeyCompany")} />
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
return { company: state.companies[ownProps.match.params.companyId] };
};
export default connect(mapStateToProps, { fetchCompany, editCompany })(
CompanyMasterEdit
);
class CompanyMasterForm extends React.Component {
render() {
const { initialValues } = this.props;
return (
<form className="ui form error">
<Field
label="Is This a Key Company?"
component={RadioGroup}
name="isKeyCompany"
required={true}
options={[
{ title: "Yes", value: true },
{ title: "No", value: false },
]}
checked={initialValues.isKeyCompany}
// onClick={this.setIsKeyCompany}
//onClick={(e) => this.setState({ isKeyCompany: e.target.checked })}
onClick={() => {
this.setState((prevState) => {
return { checked: !initialValues.isKeyCompany };
});
}}
/>
<button className="ui button primary">Submit</button>
</form>
);
}
}
class RadioGroup extends React.Component {
render() {
const { company, match } = this.props;
return (
<div className={className}>
<div className="inline fields">
<div className={labelClassName}>
{
label /* note: not wrapped in `<label>...</label>`, because it’s not the description of one option, but rather of the entire set. */
}
</div>
{options.map((o) => (
<label key={o.title}>
<input
type="radio"
name="isKeyCompany" // for example
checked={company.isKeyCompany === o.value} // or passed down via props
onChange={() =>
editCompany(match.params.companyId, {
...company,
isKeyCompany: o.value,
})
}
/>
{o.title}
</label>
))}
</div>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
return { company: state.companies[ownProps.match.params.companyId] };
};
export default connect(mapStateToProps, { editCompany })(RadioGroup);
我正在学习 React,但被卡住了。我正在尝试在编辑和创建组件之间共享一个表单。我真的很难弄清楚我在为无线电组初始化选中 属性 的值时做错了什么。页面加载后,我可以切换单选按钮。然而,最初两者都没有被检查。
我开始觉得我在表格上设置的 属性 不正确。
编辑组件(形成父组件):
class CompanyMasterEdit extends React.Component {
componentDidMount() {this.props.fetchCompany(this.props.match.params.companyId,this.props.match.params.companyName)}
onSubmit = (formValues) => { this.props.editCompany(this.props.match.params.companyId, formValues) }
render() {
return (
<div style={{ padding: 50 }}>
<h1 style={{ textAlign: "center" }}>Edit Company Master Record</h1>
<h5 style={{ textAlign: "center" }}>
<span style={{ color: "red" }}>*</span> indicates required field
</h5>
<CompanyMasterForm
initialValues={_.pick(
this.props.company,
"isKeyCompany",...
)}
onSubmit={this.onSubmit}
/>
const mapStateToProps = (state, ownProps) => {
return { company: state.companies[ownProps.match.params.companyId] }
}
export default connect(mapStateToProps, { fetchCompany, editCompany })( CompanyMasterEdit)
形式:
class CompanyMasterForm extends React.Component {
<form
className="ui form error"
onSubmit={this.props.handleSubmit(this.onSubmit)}
>
<Field
label="Is This a Key Company?"
component={RadioGroup}
name="isKeyCompany"
required={true}
options={[
{ title: "Yes", value: true },
{ title: "No", value: false },
]}
checked={this.props.initialValues.isKeyCompany}
// onClick={this.setIsKeyCompany}
//onClick={(e) => this.setState({ isKeyCompany: e.target.checked })}
onClick={() => {this.setState((prevState) => {return {checked: !this.props.initialValues.isKeyCompany,}})
}}
/>
<button className="ui button primary">Submit</button>
</form>
RadioButtonGroup 作为单独的组件:
class RadioGroup extends React.Component {
render() {
return (
<div className={className}>
<div className="inline fields">
<div className={labelClassName}>
<label>{label}</label>
</div>
{options.map((o) => {
const isChecked = o.value ? "true" : "false"
console.log("o.value :", o.value)
return (
<label key={o.title}>
<input
type="radio"
{...input}
value={o.value}
checked={isChecked === input.value}
/>
{o.title}
</label>
)
})}
</div>
</div>
)
}
}
// const mapStateToProps = (state) => {
// console.log("radio group state : ", state)
// return { isKeyCompany: state.form.companyMasterForm.values.isKeyCompany }
// }
// export default connect(mapStateToProps)(RadioGroup)
// export default connect(null)(RadioGroup)
export default RadioGroup
我有一个codesandbox了。我觉得我离它很近,在它周围跳舞,但我无法得到它。感谢任何帮助。
选项的值为文本(input.value 是文本,但 o.value 是布尔值)。检查的 属性 是布尔值。 ===
是 never going to be quite right,除非你解决其中一个问题。
此更改会显示一个选项。并不是说它真的是正确的改变。我们可能应该对选中的 属性.
进行稍微更稳健的比较checked={o.value == input.value}
它目前是布尔值,因为你在这里设置了它
options={[
{ title: "Yes", value: true },
{ title: "No", value: false },
]}
+1 来自@Nikki9696 的研究,但更好的解决方案是使用严格的 ===
检查并更改选项配置以具有字符串值:
options={[
{ title: "Yes", value: 'true' },
{ title: "No", value: 'false' },
]}
那是因为 "true" != true
(字符串值“true”不等于布尔值 true
,即使有类型强制)。 "false"
和 false
之间的比较也是如此。
几点说明:
- 互斥的单选按钮应该有相同的
name
属性。所以我们可以只为一组选项写一个硬编码字符串。 -
value
属性不决定单选按钮是否激活。这是通过checked
/defaultChecked
完成的。如果我们有两个以上的选项(标记每个选项),value
属性特别有用。 - 上一个代码示例中变量
input
的作用不是很清楚? - 如果只有两个可能的值,最好避免将
"true"
和"false"
作为字符串值。在这种情况下,布尔值(true
或false
不带引号)更合适。这是表示状态的最简单方法,"True"
等拼写错误不会漏掉(当您使用字符串时,此类拼写错误将不会被注意到)。 - 如果您使用 uncontrolled components(即输入的值未保存在组件的状态中),您应该使用
defaultChecked
而不是checked
,如果您愿意的话用户能够在页面加载后切换复选框。 - 如果您想在应用的其他地方重复使用复选框的状态,则必须使用 controlled components。在这种情况下,设置状态也应该略有不同(见下文)。
编辑:一些补充说明以回应您在下方的评论。
(您提供的代码原样包含语法错误,如果代码正确且尽可能少(且格式正确),则更容易提供帮助。)
- 你不应该设置你的状态
onSubmit
(在表单元素上),就像你在这里所做的那样。更改应设置为onChange
(在输入元素上),因为输入元素的状态 是 您应用程序的相应状态,因此它们必须始终同步。 - 实际上设置状态的函数似乎是
editCompany
reducer。因此,您应该通过将其从父组件向下传递(丑陋)或通过将输入组件连接到 Redux 存储(清洁器)来使其对input
元素可用。
class CompanyMasterEdit extends React.Component {
componentDidMount() {
const { fetchCompany, match } = this.props;
fetchCompany(match.params.companyId, match.params.companyName);
}
render() {
const { company } = this.props;
return (
<div style={{ padding: 50 }}>
<h1 style={{ textAlign: "center" }}>Edit Company Master Record</h1>
<h5 style={{ textAlign: "center" }}>
<span style={{ color: "red" }}>*</span> indicates required field
</h5>
<CompanyMasterForm initialValues={_.pick(company, "isKeyCompany")} />
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
return { company: state.companies[ownProps.match.params.companyId] };
};
export default connect(mapStateToProps, { fetchCompany, editCompany })(
CompanyMasterEdit
);
class CompanyMasterForm extends React.Component {
render() {
const { initialValues } = this.props;
return (
<form className="ui form error">
<Field
label="Is This a Key Company?"
component={RadioGroup}
name="isKeyCompany"
required={true}
options={[
{ title: "Yes", value: true },
{ title: "No", value: false },
]}
checked={initialValues.isKeyCompany}
// onClick={this.setIsKeyCompany}
//onClick={(e) => this.setState({ isKeyCompany: e.target.checked })}
onClick={() => {
this.setState((prevState) => {
return { checked: !initialValues.isKeyCompany };
});
}}
/>
<button className="ui button primary">Submit</button>
</form>
);
}
}
class RadioGroup extends React.Component {
render() {
const { company, match } = this.props;
return (
<div className={className}>
<div className="inline fields">
<div className={labelClassName}>
{
label /* note: not wrapped in `<label>...</label>`, because it’s not the description of one option, but rather of the entire set. */
}
</div>
{options.map((o) => (
<label key={o.title}>
<input
type="radio"
name="isKeyCompany" // for example
checked={company.isKeyCompany === o.value} // or passed down via props
onChange={() =>
editCompany(match.params.companyId, {
...company,
isKeyCompany: o.value,
})
}
/>
{o.title}
</label>
))}
</div>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
return { company: state.companies[ownProps.match.params.companyId] };
};
export default connect(mapStateToProps, { editCompany })(RadioGroup);