web-dev-qa-db-fra.com

React JSX: sélection de "sélectionné" sur l'option <select> sélectionnée

Dans un composant React pour un menu <select>, je dois définir l'attribut selected sur l'option qui reflète l'état de l'application.

Dans render(), la optionState est transmise du propriétaire de l'état au composant SortMenu. Les valeurs d'option sont passées sous la forme props à partir de 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

Cependant, cela déclenche une erreur de syntaxe lors de la compilation JSX.

Faire cela supprime l'erreur de syntaxe mais ne résout évidemment pas le problème:

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

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

J'ai aussi essayé ceci:

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

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

Existe-t-il un moyen recommandé de résoudre ce problème?

335
cantera

React comprend automatiquement les booléens à cette fin, vous pouvez donc simplement écrire (remarque: non recommandé)

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

et il affichera "sélectionné" de manière appropriée.

Cependant, React vous facilite encore la tâche. Au lieu de définir selected sur chaque option, , vous pouvez (et devriez) simplement écrire value={optionsState} sur la balise de sélection elle-même :

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

Pour plus d'informations, voir le React select tag doc .

570
Sophie Alpert

Vous pouvez faire ce que React vous avertit lorsque vous essayez de définir la propriété "selected" du <option>:

Utilisez les accessoires defaultValue ou value sur <select> au lieu de définir selected sur <option>.

Donc, vous pouvez utiliser options.value sur le defaultValue de votre sélection

63
Philippe Santana

Voici une solution complète qui incorpore la meilleure réponse et les commentaires qui la suivent (ce qui pourrait aider une personne qui a du mal à tout comprendre):

UPDATE FOR ES6 (2019) - utilisation des fonctions de flèche et de la déstructuration des objets

en composante principale:

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

}

composant inclus (qui est maintenant une fonction sans état):

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

RÉPONSE PRÉCÉDENTE (en utilisant bind):

en composante principale:

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

}

composant inclus (qui est maintenant une fonction sans état):

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

le composant principal conserve la valeur sélectionnée pour fruit (en état), le composant inclus affiche l'élément select et les mises à jour sont renvoyées au composant principal pour mettre à jour son état (qui est ensuite renvoyé au composant inclus pour modifier la valeur sélectionnée).

Notez l'utilisation d'un nom prop qui vous permet de déclarer une seule méthode handleChange pour d'autres champs du même formulaire, quel que soit leur type.

17
Andy Lorenz

Voici le dernier exemple de la façon de le faire. From react docs , plus la syntaxe de la méthode "fat-arrow" (liaison automatique).

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
Rahil Ahmad

Ajoutez simplement comme première option de votre tag de sélection:

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

Cela deviendra par défaut et lorsque vous sélectionnerez une option valide sera définie sur votre état

3
Pietro Allievi

J'ai eu un problème avec les balises <select> qui ne sont pas mises à jour avec le correct <option> lorsque l'état change. Mon problème semblait être que si vous rendiez deux fois successivement, la première fois sans <option> présélectionné, mais la deuxième fois avec une, alors la balise <select> ne se met pas à jour lors du deuxième rendu , mais reste sur la valeur par défaut en premier.

J'ai trouvé une solution à cela en utilisant refs . Vous devez obtenir une référence à votre noeud de balise <select> (qui peut être imbriqué dans un composant), puis mettre à jour manuellement la propriété value, dans le hook componentDidUpdate.

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

J'ai une solution simple suit le HTML de base.

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

.text-hide est une classe de bootstrap, si vous n'utilisez pas bootstrap, vous êtes:

.text-hide {
  font: 0/0 a;
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}
1
Finn
***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
muthuvel

Poster une réponse similaire pour 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
daino3