React JSX: выбор "selected" для выбранного параметра

в компоненте React для <select> меню, мне нужно установить selected атрибут для параметра, отражающего состояние приложения.

на render(), the optionState передается от государственного владельца компоненту SortMenu. Значения параметров передаются в виде props от JSON.

render: function() {
  var options = [],
      optionState = this.props.optionState;

  this.props.options.forEach(function(option) {
    var selected = (optionState === option.value) ? ' selected' : '';

    options.push(
      <option value={option.value}{selected}>{option.label}</option>
    );
  });

// pass {options} to the select menu jsx

однако это вызывает синтаксическую ошибку при компиляции JSX.

это избавляет от синтаксической ошибки, но, очевидно, не решает проблема:

var selected = (optionState === option.value) ? 'selected' : 'false';

<option value={option.value} selected={selected}>{option.label}</option>

Я также попытался это:

var selected = (optionState === option.value) ? true : false;

<option value={option.value} {selected ? 'selected' : ''}>{option.label}</option>

есть ли рекомендуемый способ решения этой?

10 ответов


React автоматически понимает логические значения для этой цели, поэтому вы можете просто написать (примечание: не рекомендуется)

<option value={option.value} selected={optionsState == option.value}>{option.label}</option>

и он выведет "выбранный" соответствующим образом.

тем не менее, React делает это еще проще для вас. Вместо определения selected по каждому варианту, вы можете (и должны) просто писать value={optionsState} на самом теге select:

<select value={optionsState}>
  <option value="A">Apple</option>
  <option value="B">Banana</option>
  <option value="C">Cranberry</option>
</select>

подробнее на http://facebook.github.io/react/docs/forms.html#why-select-value.


вы можете сделать то, что React предупреждает вас, когда вы пытаетесь установить" выбранное " свойство <option>:

использовать defaultValue или value реквизит на <select> вместо selected on <option>.

Итак, вы можете использовать options.value на defaultValue твой выбор


вот полное решение, которое включает в себя лучший ответ и комментарии ниже него (что может помочь кому-то изо всех сил, чтобы собрать все это вместе):

В главных компонента:

class ReactMain extends React.Component {

  constructor(props) {
    super(props);
    // bind once here, better than multiple times in render
    this.handleChange = this.handleChange.bind(this);
    this.state = { fruit: props.item.fruit };
  }

  handleChange(event) {
    this.setState({ [event.target.name]: event.target.value });
  }

  saveItem() {
    const item = {};
    item.fruit = this.state.fruit;
    // do more with item object as required (e.g. save to database)
  }

  render() {
    return (
      <ReactExample name="fruit" value={this.state.fruit} onChange{this.handleChange} />
    )
  }

}

включенный компонент (который теперь является функцией без состояния):

export const ReactExample = (props) => (
  <select name={props.name} value={props.value} onChange={props.handleChange}>
    <option value="A">Apple</option>
    <option value="B">Banana</option>
    <option value="C">Cranberry</option>
  </select>
)

основной компонент поддерживает выбранное значение для fruit (в состоянии), включенный компонент отображает элемент select и обновления передаются обратно в основной компонент для обновления его состояние (которое затем возвращается к включенному компоненту для изменения выбранного значения).

обратите внимание на использование имени prop, которое позволяет объявлять один метод handleChange для других полей в той же форме независимо от их типа.


***Html:***
<div id="divContainer"></div>

var colors = [{ Name: 'Red' }, { Name: 'Green' }, { Name: 'Blue' }];
var selectedColor = 'Green';

ReactDOM.render(<Container></Container>, document.getElementById("divContainer"));

var Container = React.createClass({
    render: function () {
        return (
        <div>            
            <DropDown data={colors} Selected={selectedColor}></DropDown>
        </div>);
    }
});

***Option 1:***
var DropDown = React.createClass(
{
    render: function () {
        var items = this.props.data;
        return (
        <select value={this.props.Selected}>
            {
                items.map(function (item) {
                    return <option value={item.Name }>{item.Name}</option>;
                })
            }
        </select>);
    }
});

***Option 2:***
var DropDown = React.createClass(
{
    render: function () {
        var items = this.props.data;
        return (
        <select>
            {
                items.map(function (item) {
                    return <option value={item.Name} selected={selectedItem == item.Name}>{item.Name}</option>;
                })
            }
        </select>);
    }
});

***Option 3:***
var DropDown = React.createClass(
    {
        render: function () {
            var items = this.props.data;
            return (
            <select>
                {
                    items.map(function (item) {

                                            if (selectedItem == item.Name)
                    return <option value={item.Name } selected>{item.Name}</option>;
                else
                    return <option value={item.Name }>{item.Name}</option>;
                    })
                }
            </select>);
        }
    });

у меня были проблемы с <select> теги не правильные <option> при изменении состояния. Моя проблема заключалась в том, что если вы рендерите дважды подряд, в первый раз без предварительного выбора <option> но второй раз с одним, то <select> тег не обновляется во втором рендеринге, но остается на первом по умолчанию .

я нашел решение с помощью refs. Вам нужно получить ссылку на ваш <select> узел тегов (который может быть вложенным в каком-то компоненте), а затем вручную обновите value свойство на нем, в componentDidUpdate крюк.

componentDidUpdate(){
  let selectNode = React.findDOMNode(this.refs.selectingComponent.refs.selectTag);
  selectNode.value = this.state.someValue;
}

просто добавьте в качестве первого варианта тега select:

<option disabled hidden value=''></option>

это станет значением по умолчанию, и когда вы выберете допустимый параметр, он будет установлен в вашем состоянии


публикация аналогичного ответа для MULTISELECT / optgroups:

render() {
  return(
    <div>
      <select defaultValue="1" onChange={(e) => this.props.changeHandler(e.target.value) }>
        <option disabled="disabled" value="1" hidden="hidden">-- Select --</option>
        <optgroup label="Group 1">
          {options1}
        </optgroup>
        <optgroup label="Group 2">
          {options2}
        </optgroup>
      </select>
    </div>
  )
}

вот последний пример того , как это сделать, из react docs

        class FlavorForm extends React.Component {
         constructor(props) {
         super(props);
         this.state = {value: 'coconut'};

         this.handleChange = this.handleChange.bind(this);
         this.handleSubmit = this.handleSubmit.bind(this);
        }

        handleChange(event) {
        this.setState({value: event.target.value});
        }

        handleSubmit(event) {
        alert('Your favorite flavor is: ' + this.state.value);
        event.preventDefault();
        }

        render() {
         return (
           <form onSubmit={this.handleSubmit}>
            <label>
             Pick your favorite La Croix flavor:
             <select value={this.state.value} onChange={this.handleChange}>
             <option value="grapefruit">Grapefruit</option>
             <option value="lime">Lime</option>
             <option value="coconut">Coconut</option>
             <option value="mango">Mango</option>
           </select>
           </label>
           <input type="submit" value="Submit" />
         </form>
       );
       }
       } 

у меня есть простое решение, следующее за HTML basic.

<input
  type="select"
  defaultValue=""
  >
  <option value="" disabled className="text-hide">Please select</option>
  <option>value1</option>
  <option>value1</option>
</input>

.text-hide является классом bootstrap, если вы не используете bootstrap, вот вы:

.text-hide {
  font: 0/0 a;
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}

Я обошел аналогичную проблему, установив defaultProps:

ComponentName.defaultProps = {
  propName: ''
}

<select value="this.props.propName" ...

поэтому теперь я избегаю ошибок при компиляции, если моя опора не существует до монтажа.