如何在React中渲染选中的单选按钮

rex*_*rex 3 javascript reactjs

我找到了基于JSON数据的预检单选按钮的解决方案,但我认为代码可以改进.或者应该有更好的方法来实现它.数据结构如下:

  {
        radioA: 'Radio A',
        radioB: 'Radio B',
        radioC: 'Radio C',
        selected: 'Radio A'
    }
Run Code Online (Sandbox Code Playgroud)

不确定这是否是最好的方法.如果需要,可以修改数据结构.

根据提供的数据,我正在渲染单选按钮,其中一个预选.以下是我所拥有的.

var App = React.createClass({

getInitialState: function(){
    return {
        radioA: 'Radio A',
        radioB: 'Radio B',
        radioC: 'Radio C',
        selected: 'Radio A'
    }
},

render: function(){
    return(
        <div>                
            {Object.keys(this.state).map(function(key) {
                // Not displaying the selected data
                if(key !== 'selected'){

                    // Checked radio button
                    if(this.state[key] == this.state['selected']){
                        return(
                            <div>
                                <label className="radio-inline" key={key} htmlFor={key}>
                                    <input id={key} type="radio" checked value={key} /> {this.state[key]}
                                </label>
                            </div>
                        );
                    }

                    else{
                        return(
                            <div>
                                <label className="radio-inline" key={key} htmlFor={key}>
                                    <input id={key} type="radio" value={key} /> {this.state[key]}
                                </label>
                            </div>
                        );
                    }
                }
            }, this)} 
        </div>
    );
 }
 });

 React.render(<App />, document.getElementById('container'));
Run Code Online (Sandbox Code Playgroud)

代码是在jsfiddle.com之后设置的 https://jsfiddle.net/rexonms/2x7ey2L5/

有没有更好的解决方案来实现这个?提前致谢

Jor*_*ing 6

确实有更好的方法.在您的render方法中,if语句的两个分支内的JSX 是相同的,除了一个有checked,另一个没有.像这样的重复可以 - 而且应该 - 几乎总是被清理干净.

注意:这个答案是用React 0.14编写的.要查看使用更现代的React习语编写的代码,请参阅此修订版.

对于像checkedJSX 这样的布尔属性,您可以为它们提供一个truthy或falsy值来控制呈现的HTML元素是否具有该属性.换句话说,如果你有<input checked={10 > 1}/>,你会得到<input checked/>.如果你有<input checked={10 > 100}/>,你会得到<input/>.

考虑到这一点,我们可以将您的代码减少到这样的:

var App = React.createClass({
  getInitialState: function() {
    return {
      radios: {
        radioA: 'Radio A',
        radioB: 'Radio B',
        radioC: 'Radio C'
      },
      selected: 'radioA'
    }
  },

  renderRadioWithLabel: function(key) {
    var isChecked = key === this.state.selected;

    return (
      <label className="radio-inline" key={key} htmlFor={key}>
        <input id={key} type="radio" checked={isChecked} value={key} />
        {this.state.radios[key]}
      </label>
    );
  },
    
  render: function() {
    return (
      <div>
        {Object.keys(this.state.radios).map(function(key) {
          return this.renderRadioWithLabel(key);
        }, this)}
      </div>
    );
  }
});
 
React.render(<App />, document.getElementById('container'));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="container"></div>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我已经打破了将单选按钮及其标签呈现为自己的功能的逻辑.您不必这样做,但我发现它使render内部循环的函数更容易阅读,并使您的意图更清晰.

包括我自己在内的一些人会主张将这种逻辑分解为自己的组件,这样你就可以拥有一个有状态的容器组件和无状态的子组件,这使得整个事情变得更加容易,更容易测试.这是一篇关于这个主题的好文章.您可能想要做的另一件事是在数组中创建键和标签列表,因为在JavaScript中无法保证对象属性的顺序.如果您想知道这些更改可能会是什么样子,请查看以下代码段:

var Radio = React.createClass({
  render: function() {
    var key = this.props.key;
    return (
      <label className="radio-inline" key={key} htmlFor={key}>
        <input id={key} type="radio" checked={this.props.selected} value={key} />
        {this.props.label}
      </label>
    );
  }
});

var RadiosContainer = React.createClass({
  getInitialState: function() {
    return { selected: this.props.initialSelected };
  },
  
  render: function() {
    return (
      <div>
        {this.props.radios.map(function(radioProps) {
          var selected = this.state.selected === radioProps.key;
          return <Radio {...radioProps} selected={selected} />;
        }, this)}
      </div>
    );
  }
});

var radios = [
  { key: 'radioA', label: 'Radio A' },
  { key: 'radioB', label: 'Radio B' },
  { key: 'radioC', label: 'Radio C' }
];
var selectedRadio = 'radioB';

React.render(
  <RadiosContainer radios={radios} initialSelected={selectedRadio} />, 
  document.getElementById('container')
);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="container"></div>
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,您在jsfiddle上的示例无法正常工作-您无法更改单选按钮。 (2认同)