【问题标题】:How do I make a reusable radio button with reactJS?如何使用 reactJS 制作可重复使用的单选按钮?
【发布时间】:2016-11-07 22:31:10
【问题描述】:

我尝试按照此处的说明进行操作: http://react.tips/radio-buttons-in-reactjs/

这段代码几乎可以工作,但我似乎无法弄清楚哪里出了问题。使用两个单选选项,单击选定的单选按钮会将选择更改为另一个选项。单击未选中的收音机不会执行任何操作。我已经尝试了很多东西,但似乎没有什么能让收音机按预期工作。单击未选中的选项将其选中。

这是我的代码:(*已更新)

var RadioInput = React.createClass({
getInitialState: function () {
    return {selectedOption: "0"};
},
handleOptionChange: function (changeEvent) {
    this.setState({selectedOption: changeEvent.target.value});
    console.log(this.state.selectedOption, changeEvent.target, this.props.inputValue);
},    
render: function () {
  var isChecked = this.state.selectedOption === this.props.inputValue;
  return (<p><label>
          <input type="radio" name={this.props.inputName} value={this.props.inputValue}  checked={isChecked} onChange={this.handleOptionChange}/>{this.props.labelText}
    </label></p>);
}
});

我希望有了这个通用的 RadioInput,我可以在其他组件中重用它,将一堆表单输入编译在一起......就像我在下面做的......

var MediaInfo = React.createClass({
render: function () {
    return (
        <div className="thumbnail">
            <div className="caption text-center">
                <h3>Media Contact Options</h3>
                <form className="text-left">
                    <p>Please indicate your contact preferences for media inquiries below:</p>
                    <div className="form-group">
                        <div className="col-md-12">
                            {this.props.fields.options.map (function (data, i) {
                                return (<RadioInput key={i} inputName={data.inputName} labelText={data.labelText} inputValue={data.inputValue} />);
                            })}



                        </div>
                    </div>
                    {this.props.fields.fields.map (function (data, i) {
                        return (<TextInput key={i} inputName={data.inputName} labelText={data.labelText} placeholderText={data.placeholderText} inputValue={data.inputValue} />);
                    })}
                </form>
            </div>
        </div>            
    )
}
});
var MemberInfo = React.createClass({
getInitialState: function () {
    return {
        contactInfo: [  {inputName:"fullName", labelText:"Display Name", placeholderText:"Enter Full Name", inputValue:"some name"},
                        {inputName:"phoneNumber", labelText:"Phone Number", placeholderText:"Enter Phone Number", inputValue:"001-555-1234"},
                        {inputName:"email", labelText:"Email", placeholderText:"Enter Email", inputValue:"mr.fake@someplace.com"},
                        {inputName:"address", labelText:"Address", placeholderText:"Enter Address", inputValue:"123 Main St. Podunk, FL"}
                     ],
        mediaContact: {fields: [ {inputName: "email", labelText: "Media Email", placeholderText:"Enter Medial Contact Email", inputValue:"get@me.dog"},
                        {inputName: "phone", labelText: "Media Phone", placeholderText:"Media Contact Phone Number", inputValue:"001-555-1234"},
                      ],
                      options: [
                          {inputName: "mediaConsent", labelText: " Yes, I would like to be contacted by the Media.", inputValue:"1"},
                          {inputName: "mediaConsent", labelText: " No, I do not wish to be contacted by the Media.", inputValue:"0"}
                      ]
                      }
    }
},
render: function () {
    return (
                    <div className="panel panel-default">
                        <div className="panel-heading">
                            <h3 className="panel-title">Manage Your Contact Info</h3> </div>
                        <div className="panel-body">
                            <div className="col-md-6">
                                <div className="row">
                                    <div className="col-xs-12">
                                        <ContactInfo fields={this.state.contactInfo} />
                                    </div>
                                </div>
                            </div>
                            <div className="col-md-6">
                                <div className="row">
                                    <div className="col-xs-12">
                                        <MediaInfo fields={this.state.mediaContact} />
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
    );

},

});

【问题讨论】:

  • 你能举一个活生生的例子吗?展示你如何渲染它?
  • 我更新了我的代码以显示 组件是如何在另一个组件中使用的。整个 组件呈现如下: ReactDOM.render(, document.querySelectorAll('#member-info')[0]);

标签: reactjs


【解决方案1】:

如果你想使用多个单选按钮,你需要设置一个name 属性。此外,如果只有一个单选按钮,则不能取消选中(使用复选框)。

var RadioInput = React.createClass({
  getInitialState: function() {
    return { selectedOption: false };
  },

  handleOptionChange: function(e) {
    this.setState({ selectedOption: e.target.value });
  },

  render: function() {
    var isChecked = this.state.selectedOption === this.props.inputValue;
    return (
      <p><label>
        <input
          type="radio"
          value={this.props.value}
          name={this.props.name}
          selected={isChecked}
          onChange={this.handleOptionChange} />
          {this.props.value}
      </label></p>
    );
  }
});

ReactDOM.render(<form>
                 <RadioInput name="group" value="one" />
                 <RadioInput name="group" value="two" />
                </form>, document.getElementById('View'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="View"></div>

【讨论】:

  • 该组件设计用于从数组中加载数据...看看更新后的代码。
【解决方案2】:

我找到了一个似乎运作良好的解决方案,并且我相信状态和道具的正确使用(但我只是掌握了它们,所以如果我错了,请纠正我)。

我添加了选定的选项值和一个用于将选定选项的状态更新到维护整个表单状态的父组件的函数:

var MemberInfo = React.createClass({
setSelectedOption: function (updatedValues) {
    var newSelected = this.state.mediaContact;
    newSelected.selectedOption = updatedValues;
    this.setState({ mediaContact: newSelected });
},
getInitialState: function() { return {...     
mediaContact: {..., selectedOption: "0"}}},

我将 setSelectedOption 传递给负责将表单组件渲染为 prop 的组件:

<MediaInfo fields={this.state.mediaContact} setSelectedOption={this.setSelectedOption} />

我向我的 RadioInput 组件添加了一个选定的道具,并使用 state 属性计算了值。我还将 setSelectedOption 函数作为道具传递给每个渲染的 RadioInput 作为道具。 这可能不是一个理想的实现方式。

{this.props.fields.options.map (function (data, i) {
                                return (<RadioInput key={i} 
                                            inputName={data.inputName} 
                                            labelText={data.labelText} 
                                            inputValue={data.inputValue} 
                                            setSelectedOption={this.props.setSelectedOption}
                                            selected={this.props.fields.selectedOption === data.inputValue}
                                            />);
                            }.bind(this))}

现在我的组件没有状态,恕我直言,它不应该有状态,只是一个 onChange 处理程序:

var RadioInput = React.createClass({
handleOptionChange: function (changeEvent) {
    this.props.setSelectedOption(changeEvent.target.value);
},    
render: function () {
  return (<p><label>
          <input type="radio" name={this.props.inputName} value={this.props.inputValue}  checked={this.props.selected} onChange={this.handleOptionChange}/>{this.props.labelText}
    </label></p>);
}
});

最重要的是,呈现的无线电输入按预期运行...默认选中,当用户单击另一个选项时,选择会更改。

下面是完整的代码。我的目标是创建一种使用 reactJS 创建引导表单并使用来自 API 的数据填充它的方法。我还没有编写代码来保存数据或从 API 中提取数据。我的计划是添加一些按钮并使用按钮的 onClick 处理程序来提交数据。除此之外,我只需要添加 componentDidMount 函数来填充来自 API 的数据。希望这对某人有所帮助。

var TextInput = React.createClass({
    handleChange: function (event) {
        var updatedValues = {
            inputName: this.props.inputName,
            placeholderText: this.props.placeHolderText,
            labelText:this.props.labelText,
            inputValue:event.target.value, 
        }; 
        this.props.setContactInfo(updatedValues);
    },
    render: function () {
        return (
        <div className="form-group">
            <label htmlFor={this.props.inputName}>{this.props.labelText}</label>
            <input onChange={this.handleChange} className="form-control" id={this.props.inputName} placeholder={this.props.placeholderText} value={this.props.inputValue} />
        </div> );       
    },
});

var RadioInput = React.createClass({
    handleOptionChange: function (changeEvent) {
        this.props.setSelectedOption(changeEvent.target.value);
    },    
    render: function () {
      return (<p><label>
              <input type="radio" name={this.props.inputName} value={this.props.inputValue}  checked={this.props.selected} onChange={this.handleOptionChange}/>{this.props.labelText}
        </label></p>);
    }
});

var ContactInfo = React.createClass({
    render: function () {
      return (
        <div className="thumbnail">
            <div className="caption text-center">
                <h3>Member Contact Information</h3>
                <form className="text-left" action="" method="post">
                    <input type="hidden" name="member contact info" />
                    {this.props.fields.map (function (data, i) {
                        return (<TextInput 
                                    key={i} 
                                    inputName={data.inputName} 
                                    labelText={data.labelText} 
                                    placeholderText={data.placeholderText} 
                                    inputValue={data.inputValue} 
                                    setContactInfo={this.props.setContactInfo}
                                    />);
                    }.bind(this))}
                </form>
            </div>
        </div>      
      );  
    },
});

var MediaInfo = React.createClass({
    render: function () {
        console.log(this.props.fields);
        return (
            <div className="thumbnail">
                <div className="caption text-center">
                    <h3>Media Contact Options</h3>
                    <form className="text-left">
                        <p>Please indicate your contact preferences for media inquiries below:</p>
                        <div className="form-group">
                            <div className="col-md-12">
                                {this.props.fields.options.map (function (data, i) {
                                    return (<RadioInput key={i} 
                                                inputName={data.inputName} 
                                                labelText={data.labelText} 
                                                inputValue={data.inputValue} 
                                                setSelectedOption={this.props.setSelectedOption}
                                                selected={this.props.fields.selectedOption === data.inputValue}
                                                />);
                                }.bind(this))}
                            </div>
                        </div>
                        {this.props.fields.fields.map (function (data, i) {
                            return (<TextInput 
                                        key={i} 
                                        inputName={data.inputName} 
                                        labelText={data.labelText} 
                                        placeholderText={data.placeholderText} 
                                        inputValue={data.inputValue} 
                                        setContactInfo={this.props.setContactInfo} />);
                        }.bind(this))}
                    </form>
                </div>
            </div>            
        )
    }
});

var MemberInfo = React.createClass({
    setSelectedOption: function (updatedValues) {
        var newSelected = this.state.mediaContact;
        newSelected.selectedOption = updatedValues;
        this.setState({ mediaContact: newSelected });
    },
    setContactInfo: function (updatedValues) {
        var newContactInfo = this.state.contactInfo.map(function(data, i) {if(data.inputName == updatedValues.inputName) { return updatedValues;} return data });
        var newMediaInfo = this.state.mediaContact.fields.map(function(data, i) {if(data.inputName == updatedValues.inputName) { return updatedValues;} return data });
        var holdMediaContact = this.state.mediaContact;
        holdMediaContact.fields = newMediaInfo;
        this.setState({contactInfo: newContactInfo, mediaContact: holdMediaContact});
    },
    getInitialState: function () {
        return {
            contactInfo: [  {inputName:"fullName", labelText:"Display Name", placeholderText:"Enter Full Name", inputValue:""},
                            {inputName:"phoneNumber", labelText:"Phone Number", placeholderText:"Enter Phone Number", inputValue:""},
                            {inputName:"email", labelText:"Email", placeholderText:"Enter Email", inputValue:""},
                            {inputName:"address", labelText:"Address", placeholderText:"Enter Address", inputValue:""}
                         ],
            mediaContact: {fields: [ {inputName: "email", labelText: "Media Email", placeholderText:"Enter Medial Contact Email", inputValue:""},
                                     {inputName: "phone", labelText: "Media Phone", placeholderText:"Media Contact Phone Number", inputValue:""},
                                    ],
                          options:  [ {inputName: "mediaConsent", labelText: " Yes, I would like to be contacted by the Media regarding my candidacy.", inputValue:"1"},
                                      {inputName: "mediaConsent", labelText: " No, I do not wish to be contacted by the Media.", inputValue:"0"}
                                    ],
                           selectedOption: "0"
                          }
        }
    },
    render: function () {
        return (
                        <div className="panel panel-default">
                            <div className="panel-heading">
                                <h3 className="panel-title">Manage Your Contact Info</h3> </div>
                            <div className="panel-body">
                                <div className="col-md-6">
                                    <div className="row">
                                        <div className="col-xs-12">
                                            <ContactInfo fields={this.state.contactInfo} setContactInfo={this.setContactInfo} />
                                        </div>
                                    </div>
                                </div>
                                <div className="col-md-6">
                                    <div className="row">
                                        <div className="col-xs-12">
                                            <MediaInfo fields={this.state.mediaContact} setSelectedOption={this.setSelectedOption} setContactInfo={this.setContactInfo} />
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
        );

    },
});

ReactDOM.render(<MemberInfo />, document.querySelectorAll('#member-info')[0]);

【讨论】:

    猜你喜欢
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 2023-03-31
    • 2014-10-14
    • 2013-12-12
    相关资源
    最近更新 更多