javascript - 如何使用 redux\redux-form 初始化独立的 Radio Button Group 组件检查属性状态

标签 javascript reactjs react-redux redux-form radio-group

我正在学习 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向上。我觉得我很接近并在它周围跳舞,但我无法得到它。如有任何帮助,我们将不胜感激。

最佳答案

几点说明:

  • 互斥的单选按钮应具有相同的 name 属性。因此我们可以为一组选项编写一个硬编码字符串。
  • value 属性无法确定单选按钮是否处于事件状态。这是通过 checked/defaultChecked 完成的。如果我们有两个以上的选项(标记每个选项),则 value 属性特别有用。
  • 不清楚变量 input 在最后一个代码示例中的作用?
  • 如果只有两个可能的值,最好避免使用 "true""false" 作为字符串值。在这种情况下, bool 值(不带引号的 truefalse)更合适。这是表示状态的最简单方法,并且诸如“True”之类的拼写错误不会被忽视(当您使用字符串时,此类拼写错误将不会被注意到)。
  • 如果您使用uncontrolled components (即输入的值不会保留在组件的状态中),如果您希望用户能够切换复选框,则应该使用 defaultChecked 而不是 checked页面加载后。
  • 如果您想在应用中的其他位置重复使用复选框的状态,则必须使用 controlled components 。在这种情况下,设置状态的方式也应该略有不同(见下文)。

编辑:针对您在下面的评论的一些补充说明。

(您提供的代码按原样包含语法错误,如果代码正确且尽可能少(并且格式良好),则更容易提供帮助。😊)

  • 您不应该设置状态onSubmit(在表单元素上),就像您在这里所做的那样。更改应设置为 onChange(在输入元素上),因为输入元素的状态是应用程序的相应状态,因此它们必须始终保持同步。
  • 实际上设置状态的函数是 editCompany reducer 。因此,您应该使其可供 input 元素使用,方法是从父组件向下传递它(丑陋),或者将输入组件连接到 Redux 存储(更干净)。
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);

关于javascript - 如何使用 redux\redux-form 初始化独立的 Radio Button Group 组件检查属性状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70615168/

相关文章:

javascript - React - 合并 2 个字符串以获取 URL

javascript - React JS 在另一个组件内调用函数

javascript - 从商店发货后获取数据

reactjs - TypeScript 返回 Redux Action 的类型

javascript - THREE.js - 如何实现这种效果?

javascript - 使用 AngularJS 观察输入变化

javascript - 鼠标点击限制问题,如alert()

javascript - 创建圆后显示 OpenLayers 边界

javascript - 在 React 中更改图标的颜色

javascript - React 中特定样式的 HTML 标签