Reagisci JSX: selezionando “selezionato” sull'opzione <seleziona> selezionata


403

In un componente React per un <select>menu, devo impostare l' selectedattributo sull'opzione che riflette lo stato dell'applicazione.

In render(), optionStateviene passato dal proprietario dello stato al componente SortMenu. I valori delle opzioni vengono passati come propsda 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

Tuttavia, ciò genera un errore di sintassi nella compilazione JSX.

In questo modo elimina l'errore di sintassi ma ovviamente non risolve il problema:

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

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

Ho anche provato questo:

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

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

C'è un modo consigliato per risolvere questo?


Valorizzazione della domanda solo per il titolo
ericgio

Risposte:


649

React capisce automaticamente i booleani per questo scopo, quindi puoi semplicemente scrivere (nota: non raccomandato)

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

e produrrà 'selezionato' in modo appropriato.

Tuttavia, React rende questo ancora più facile per te. Invece di definire selectedsu ciascuna opzione, puoi (e dovresti) semplicemente scrivere value={optionsState}sul tag select stesso :

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

Per ulteriori informazioni, vedere il documento di selezione della selezione di React .


56
Con l'attuale versione di React (0.9) l'impostazione dell'attributo selezionato sulle opzioni non funziona affatto. Impostare invece l'attributo value sull'elemento select.
liammclennan,

2
carico i dati con ajax.defaultValue non funziona per me. il valore funziona ma non posso selezionare un altro elemento nell'elenco di selezione. L'elenco si apre ma quando seleziono uno di essi seleziona l'elemento di valore. Qualche idea?
user1924375,

5
@ user1924375 dovresti usare l'evento onChange onChange={this.handleSelect}e impostare il valore dello stato per il tuo componente, ad esempio: 'handleSelect: function () {this.setState ({value: event.target.value});} `Questo renderebbe il tuo nuovo componente selezionato con nuovo oggetto selezionato. Spero che ti possa aiutare.
funnydaredevil,

1
Sebbene non sia ancora documentato, il valueprop su a <select>può essere un array se lo hai multiselectabilitato.
tirdadc,

4
Piuttosto usa defaultValueper inizializzare
dewwwald

70

Puoi fare ciò che React ti avverte quando tenti di impostare la proprietà "selezionata" di <option>:

Utilizzare il defaultValueo valueoggetti di scena sul <select>posto di impostazione selectedsu <option>.

Quindi, è possibile utilizzare options.valueil defaultValuedi selezionare


9
Se desidero ancora indicare l'opzione attualmente selezionata, come farei comunque? L'unico modo in cui sono attualmente in grado di mantenere effettivamente l'opzione selezionata (e mantenere lo stato del modulo per il POST futuro) è impostando select = true. Ho provato a impostare defaultValue e value props dell'elemento select, ma questo non viene visualizzato nella vista impostando l'opzione corretta su selezionata nel menu delle opzioni. Qualche consiglio?
The Pied Pipes,

4
Esempio forse ??
shinzou,

1
Non funziona per me: <select className = "form-control" value = "Mois">
Kuartz

2
defaultValue non funziona con la versione più recente
Hos Mercury

18

Ecco una soluzione completa che incorpora la migliore risposta e i commenti sottostanti (che potrebbero aiutare qualcuno che fatica a mettere tutto insieme):

AGGIORNAMENTO PER ES6 (2019): utilizzo delle funzioni freccia e distruzione degli oggetti

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

}

componente incluso (che ora è un funzionale apolide):

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

RISPOSTA PRECEDENTE (usando il bind):

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

}

componente incluso (che ora è un funzionale apolide):

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

il componente principale mantiene il valore selezionato per fruit (nello stato), il componente incluso visualizza l'elemento selezionato e gli aggiornamenti vengono passati al componente principale per aggiornare il suo stato (che quindi ritorna al componente incluso per modificare il valore selezionato).

Si noti l'uso di un nome prop che consente di dichiarare un singolo metodo handleChange per altri campi nello stesso modulo indipendentemente dal loro tipo.


Nota che la linea nel costruttore this.handleChange.bind(this);dovrebbe essere this.handleChange = this.handleChange.bind(this);
Will Shaver,

per quelli di voi che come me chiedendo loro auto Ma che ... significa: reactjs.org/docs/jsx-in-depth.html#spread-attributes
talsibony

@talsibony - questo è davvero l'operatore di diffusione, ma nel mio codice di esempio significa semplicemente inserire un altro codice qui !
Andy Lorenz,

@AndyLorenz Quindi in quel caso consiglierei di rimuoverlo ... :), o semplicemente scrivere un commento come // resto del codice
talsibony

8

Ecco l'ultimo esempio di come farlo. Dai documenti di reazione , più la sintassi del metodo "fat-arrow" auto-binding.

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

Aggiungi semplicemente come prima opzione del tag select:

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

Questo diventerà predefinito e quando selezionerai un'opzione valida verrà impostata sul tuo stato


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
Anche se non è stata fornita alcuna spiegazione, non ne era davvero necessaria una. I molteplici modi per affrontare lo stesso problema sono stati davvero utili. Grazie
DJ2 il

0

Ho avuto un problema con i <select>tag che non si aggiornavano correttamente <option>quando cambia lo stato. Il mio problema sembra essere che se si esegue il rendering due volte in rapida successione, la prima volta senza pre-selezionato, <option>ma la seconda volta con uno, il <select>tag non si aggiorna sul secondo rendering, ma rimane sul primo predefinito.

Ho trovato una soluzione a questo usando refs . È necessario ottenere un riferimento al <select>nodo del tag (che potrebbe essere nidificato in alcuni componenti), quindi aggiornare manualmente la valueproprietà su di esso, componentDidUpdatenell'hook.

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

0

Pubblicare una risposta simile per 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

Ho una soluzione semplice sta seguendo l'HTML di base.

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

.text-hide è una classe di bootstrap, se non usi bootstrap, eccoti qui:

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

-1

Ho aggirato un problema simile impostando defaultProps:

ComponentName.defaultProps = {
  propName: ''
}

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

Quindi ora evito errori di compilazione se il mio prop non esiste fino al montaggio.


Questo non sta davvero risolvendo il problema. Otterrai questo: Avviso: Tipo di prop non riuscito: hai fornito un valueprop a un campo modulo senza un onChangegestore. Questo renderà un campo di sola lettura. Se il campo deve essere modificabile, utilizzare defaultValue. Altrimenti, impostare onChangeo readOnly.
Jason Rice,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.