React JSX: вибір "вибраного" у вибраній опції <select>


402

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

У render(), 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>

Чи є рекомендований спосіб вирішення цього питання?


Оголошення питання лише на заголовок
ericgio

Відповіді:


647

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>

Для отримання додаткової інформації див. Тег doc .


56
У поточній версії React (0.9) встановлення вибраного атрибута на параметри взагалі не працює. Встановіть атрибут значення замість елемента вибору.
liammclennan

2
я завантажую дані з ajax.defaultValue для мене не працює. Значення працює, але я не можу вибрати інший елемент у списку вибору. Список відкривається, але коли я вибираю один із них, він вибирає значення. Яка ідея?
користувач1924375

5
@ user1924375 ви повинні використовувати подію onChange onChange={this.handleSelect}і встановити значення стану для свого компонента, наприклад: 'handleSelect: function () {this.setState ({value: event.target.value});} `Це перетворить ваш вибраний компонент на новий вибраний елемент. Сподіваюся, це допоможе вам.
funnydaredevil

1
Хоча це ще не задокументовано, valueопора на аркуші <select>може бути масивом, якщо ви multiselectввімкнули.
tirdadc

4
Швидше використовувати defaultValueдля ініціалізації
dewwwald

70

Ви можете зробити те, на що React попереджає вас, намагаючись встановити "вибране" властивість <option>:

Використовуйте defaultValueабо valueреквізит на <select>замість установки selectedна <option>.

Таким чином, ви можете використовувати options.valueна defaultValueз вашого вибору


9
Якщо я хочу все-таки вказати варіант, який зараз обраний, як би це зробити? Єдиний спосіб, яким я в даний час можу фактично утримувати вибраний параметр (і зберігати стан форми для майбутньої POSTing), встановивши select = true. Я спробував встановити параметр defaultValue та value для елемента вибору, але це не відображається у поданні, встановивши правильну опцію для вибраного в меню параметрів. Будь-яка порада?
The Pied Pipes

4
Приклад, можливо ??
shinzou

1
Не працює для мене: <select className = "form-control" value = "Mois">
Kuartz

2
defaultValue не працює з новітньою версією
Hos Mercury

18

Ось повне рішення, яке містить найкращу відповідь та коментарі під нею (що може допомогти комусь, хто бореться зібрати все це разом):

ОНОВЛЕННЯ ДЛЯ ES6 (2019) - за допомогою функцій стрілок та знищення об’єктів

в основному компоненті:

class ReactMain extends React.Component {

  constructor(props) {
    super(props);
    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} handleChange={this.handleChange} />
    )
  }

}

включений компонент (який тепер функціонує без громадянства):

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

ПОПЕРЕДНЯ ВІДПОВІДЬ (за допомогою палітурки):

в основному компоненті:

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} handleChange={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>
)

основний компонент підтримує вибране значення для фруктів (у стані), включений компонент відображає вибраний елемент, а оновлення передаються до основного компонента для оновлення його стану (який потім цикли повертаються на включений компонент для зміни вибраного значення).

Зверніть увагу на використання імені підпорядкування, яке дозволяє оголосити метод єдиної ручки зміни для інших полів у тій же формі незалежно від їх типу.


Зверніть увагу, що рядок у конструкторі this.handleChange.bind(this);повинен бути this.handleChange = this.handleChange.bind(this);
Буде Шейвер

для тих з вас, як я, які запитують у себе, що таке ... означає: reactjs.org/docs/jsx-in-depth.html#spread-attributes
талісбоні

@talsibony - це дійсно оператор розповсюдження, але в моєму зразковому коді це просто означає вставити ще якийсь код !
Енді Лоренц

@AndyLorenz Тож у такому випадку я б рекомендував видалити його ... :) або просто написати коментар, як // решта вашого коду
talsibony

8

Ось останній приклад того, як це зробити. Від реагувати на документи , а також синтаксис методу автоматичного прив’язки «жир-стрілка».

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

  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 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>
    );
  }
} 

4

Просто додайте в якості першого варіанту вибраний тег:

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

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


1
***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>);
        }
    });

1
Незважаючи на те, що ніяких пояснень не було, воно насправді не було потрібне. Кілька способів наблизитися до однієї і тієї самої проблеми були дуже корисними для розуміння. Дякую
DJ2

0

У мене виникла проблема з <select>не оновленням тегів до правильних, <option>коли стан змінюється. Моя проблема, здавалося, полягає в тому, що якщо ви рендеруєте двічі швидкою послідовністю, перший раз без попереднього вибору, <option>але другий раз з одним, <select>тег не оновлюється на другому візуалізації, а залишається за замовчуванням першим.

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

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

0

Опублікуйте аналогічну відповідь для 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>
  )
}

0

У мене просте рішення - це слідування основним HTML.

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

.text-hide - клас завантаження, якщо ви не використовуєте bootstrap, ось ви:

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

-1

Я вирішив подібну проблему, встановивши defaultProps:

ComponentName.defaultProps = {
  propName: ''
}

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

Тож тепер я уникаю помилок під час компіляції, якщо моя опора не існує до монтажу.


Це справді не вирішує проблему. Ви отримаєте це: Попередження: Невдалий тип опори: Ви надали valueопору для поля форми без onChangeобробника. Це виведе поле лише для читання. Якщо поле має бути зміненим, використовуйте defaultValue. В іншому випадку встановіть onChangeабо readOnly.
Джейсон Райс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.