React JSX: sélection de «sélectionné» sur l'option <sélectionner> sélectionnée

403

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

Dans render(), le optionStateest transmis du propriétaire de l'État au composant SortMenu. Les valeurs des options sont transmises à partir propsde 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.

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 également 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?

cantera
la source
Vote pour la question juste pour le titre
ericgio

Réponses:

649

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

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

et il sortira «sélectionné» de manière appropriée.

Cependant, React vous facilite la tâche. Au lieu de définir selectedsur chaque option, vous pouvez (et devriez) simplement écrire value={optionsState}sur la balise select 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, consultez le document React select tag .

Sophie Alpert
la source
56
Avec la version actuelle de React (0.9), la définition de l'attribut sélectionné sur les options ne fonctionne pas du tout. Définissez plutôt l'attribut value sur l'élément select.
liammclennan
2
je charge des données avec ajax.defaultValue ne fonctionne pas pour moi. la valeur fonctionne, mais je ne peux pas sélectionner un autre élément sur la liste de sélection.La liste s'ouvre mais lorsque je sélectionne l'un d'eux, il sélectionne l'élément de valeur.Une idée?
user1924375
5
@ user1924375 vous devez utiliser l'événement onChange onChange={this.handleSelect}et définir la valeur d'état pour votre composant, par exemple: 'handleSelect: function () {this.setState ({value: event.target.value});} `Cela rendrait votre composant sélectionné avec de nouveaux Élément sélectionné. J'espère que cela vous aidera.
funnydaredevil
1
Bien qu'il ne soit pas encore documenté, l' valueaccessoire sur un <select>peut être un tableau si vous l'avez multiselectactivé.
tirdadc
4
Plutôt utiliser defaultValue pour initialiser
dewwwald
70

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

Utilisez le defaultValueou valueaccessoires à la <select>place de la fixation selectedsur <option>.

Ainsi, vous pouvez utiliser options.valuesur defaultValuevotre choix

Philippe Santana
la source
9
Si je souhaite toujours indiquer l'option actuellement sélectionnée, comment dois-je procéder? La seule façon dont je suis actuellement en mesure de conserver l'option sélectionnée (et de conserver l'état du formulaire pour les futures publications) est de définir select = true. J'ai essayé de définir les accessoires defaultValue et value de l'élément select, mais cela ne s'affiche pas dans la vue en définissant l'option correcte sur selected dans le menu d'options. Aucun conseil?
The Pied Pipes
4
Exemple peut-être ??
shinzou
1
Ne fonctionne pas pour moi: <select className = "form-control" value = "Mois">
Kuartz
2
defaultValue ne fonctionne pas avec la dernière version
Hos Mercury
18

Voici une solution complète qui incorpore la meilleure réponse et les commentaires ci-dessous (qui pourraient aider quelqu'un qui a du mal à tout reconstituer):

MISE À JOUR POUR ES6 (2019) - Utilisation des fonctions fléchées et de la déstructuration d'objets

dans le composant principal:

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 (à l'aide de bind):

dans le composant principal:

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 les fruits (en état), le composant inclus affiche l'élément sélectionné et les mises à jour sont retransmises au composant principal pour mettre à jour son état (qui revient ensuite au composant inclus pour modifier la valeur sélectionnée).

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

Andy Lorenz
la source
Notez que la ligne dans le constructeur this.handleChange.bind(this);doit être this.handleChange = this.handleChange.bind(this);
Will Shaver
pour ceux d'entre vous comme moi qui se demandent ce que le ... signifie: reactjs.org/docs/jsx-in-depth.html#spread-attributes
talsibony
@talsibony - c'est en effet l'opérateur de propagation, mais dans mon exemple de code, cela signifie simplement insérer un autre code ici !
Andy Lorenz
@AndyLorenz Donc, dans ce cas, je recommanderais de le supprimer ... :), ou écrivez simplement un commentaire comme // reste de votre code
talsibony
8

Voici le dernier exemple de la façon de procéder. À partir de React Docs , plus la syntaxe de la méthode de liaison automatique "Fat-Arrow".

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>
    );
  }
} 
Rahil Ahmad
la source
4

Ajoutez simplement la première option de votre balise de sélection:

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

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

Pietro Allievi
la source
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>);
        }
    });
muthuvel
la source
1
Même si aucune explication n'a été donnée, une n'était pas vraiment nécessaire. Les multiples façons d'aborder le même problème ont été très utiles. Merci
DJ2
0

J'ai rencontré un problème avec les <select>balises qui ne se mettent pas à jour correctement <option>lorsque l'état change. Mon problème semblait être que si vous effectuez deux rendus successifs rapidement, la première fois sans présélection <option>mais la deuxième fois avec un, le<select> balise ne se met pas à jour sur le deuxième rendu, mais reste sur la valeur par défaut en premier.

J'ai trouvé une solution à cela en utilisant des références . Vous devez obtenir une référence à votre <select>nœud de balise (qui peut être imbriqué dans certains composants), puis mettre à jour manuellement la valuepropriété sur celui-ci, dans le componentDidUpdatecrochet.

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

Publier 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>
  )
}
daino3
la source
0

J'ai une solution simple en suivant 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 bootstrap, si vous n'utilisez pas bootstrap, vous êtes ici:

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

J'ai résolu un problème similaire en définissant defaultProps:

ComponentName.defaultProps = {
  propName: ''
}

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

Alors maintenant j'évite les erreurs de compilation si mon accessoire n'existe pas avant le montage.

Matt Saunders
la source
Cela ne résout vraiment pas le problème. Vous obtiendrez ceci: Avertissement: Type d'accessoire ayant échoué: vous avez fourni un valueaccessoire à un champ de formulaire sans onChangegestionnaire. Cela rendra un champ en lecture seule. Si le champ doit être modifiable, utilisez defaultValue. Sinon, définissez soit onChangeou readOnly.
Jason Rice