如何使用reactJS制作可重复使用的单选按钮?

时间:2016-11-07 22:31:11

标签: reactjs

我尝试按照这里的说明操作: 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>
    );

},

});

2 个答案:

答案 0 :(得分:1)

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

&#13;
&#13;
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'));
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

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

我添加了所选的选项值和一个函数,用于将所选选项的状态更新为保持整个表单状态的父组件:

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函数作为prop传递给每个渲染的RadioInput作为prop。 这可能不是理想的实施方式。

{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]);