Reaccionar JSX: seleccionando "seleccionado" en la opción <seleccionar> seleccionada

403

En un componente Reaccionar para un <select>menú, necesito establecer el selectedatributo en la opción que refleja el estado de la aplicación.

En render(), optionStatese pasa del propietario del estado al componente SortMenu. Los valores de las opciones se pasan propsdesde 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

Sin embargo, eso desencadena un error de sintaxis en la compilación JSX.

Hacer esto elimina el error de sintaxis pero obviamente no resuelve el problema:

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

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

También probé esto:

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

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

¿Hay alguna forma recomendada de resolver esto?

cantera
fuente
Votando la pregunta solo por el título
ericgio

Respuestas:

649

React entiende automáticamente los booleanos para este propósito, por lo que simplemente puede escribir (nota: no recomendado)

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

y saldrá 'seleccionado' adecuadamente.

Sin embargo, React lo hace aún más fácil para usted. En lugar de definir selecteden cada opción, puede (y debería) simplemente escribir value={optionsState}en la propia etiqueta de selección :

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

Para obtener más información, consulte el documento React select tag doc .

Sophie Alpert
fuente
56
Con la versión actual de React (0.9), configurar el atributo seleccionado en las opciones no funciona en absoluto. Establezca el atributo de valor en el elemento select en su lugar.
liammclennan
2
Cargo datos con ajax.defaultValue no funciona para mí. el valor funciona pero no puedo seleccionar otro elemento en la lista de selección. La lista se está abriendo pero cuando selecciono uno de ellos selecciona el elemento de valor. ¿Alguna idea?
user1924375
55
@ user1924375 debe usar el evento onChange onChange={this.handleSelect}y establecer el valor de estado para su componente, por ejemplo: 'handleSelect: function () {this.setState ({value: event.target.value});} `Esto devolvería su componente seleccionado con nuevo item seleccionado. Espero que te ayude.
funnydaredevil
1
Aunque todavía no está documentado, el valueaccesorio en un <select>puede ser una matriz si lo ha multiselecthabilitado.
tirdadc
44
Más bien usar defaultValuepara inicializar
dewwwald
70

Puede hacer lo que React le advierte cuando intenta establecer la propiedad "seleccionada" de <option>:

Utilice el defaultValueo valuelos apoyos en <select>lugar de establecer selecteden <option>.

Por lo tanto, puede usar options.valueel defaultValuede su selección

Philippe Santana
fuente
99
Si todavía quiero indicar la opción que está seleccionada actualmente, ¿cómo lo haría? La única forma en que actualmente puedo mantener la opción seleccionada (y mantener el estado del formulario para futuras PUBLICACIONES) es estableciendo select = true. He intentado establecer los accesorios defaultValue y value del elemento select, pero esto no se muestra en la vista configurando la opción correcta a seleccionada en el menú de opciones. ¿Algún consejo?
The Pied Pipes
44
Ejemplo tal vez ??
shinzou
1
No funciona para mí: <select className = "form-control" value = "Mois">
Kuartz
2
defaultValue no funciona con la versión más reciente
Hos Mercury
18

Aquí hay una solución completa que incorpora la mejor respuesta y los comentarios a continuación (lo que podría ayudar a alguien que lucha por reconstruirlo todo):

ACTUALIZACIÓN PARA ES6 (2019): uso de funciones de flecha y desestructuración de objetos

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

}

componente incluido (que ahora es funcional sin estado):

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

RESPUESTA PREVIA (usando bind):

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

}

componente incluido (que ahora es funcional sin estado):

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

el componente principal mantiene el valor seleccionado para la fruta (en estado), el componente incluido muestra el elemento seleccionado y las actualizaciones se devuelven al componente principal para actualizar su estado (que luego vuelve al componente incluido para cambiar el valor seleccionado).

Tenga en cuenta el uso de un nombre prop que le permite declarar un solo método handleChange para otros campos en el mismo formulario, independientemente de su tipo.

Andy Lorenz
fuente
Tenga en cuenta que la línea en el constructor this.handleChange.bind(this);debe ser this.handleChange = this.handleChange.bind(this);
Will Shaver
para aquellos de ustedes como yo que se preguntan qué significa ... reactjs.org/docs/jsx-in-depth.html#spread-attributes
talsibony
@talsibony: ese es el operador de propagación, pero en mi código de muestra solo significa insertar otro código aquí .
Andy Lorenz
@AndyLorenz Entonces, en ese caso, recomendaría eliminarlo ... :), o simplemente escribir un comentario como // resto de su código
talsibony
8

Aquí está el último ejemplo de cómo hacerlo. De los documentos de reacción , más la sintaxis del método de "flecha gruesa" de enlace automático

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
fuente
4

Simplemente agregue como primera opción de su etiqueta de selección:

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

Esto se convertirá en predeterminado y cuando seleccione una opción válida se establecerá en su estado

Pietro Allievi
fuente
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
fuente
1
Aunque no se dio ninguna explicación, realmente no se necesitaba una. Las múltiples formas de abordar el mismo problema fueron realmente útiles. Gracias
DJ2
0

He tenido un problema con las <select>etiquetas que no se actualizan correctamente <option>cuando cambia el estado. Mi problema parecía ser que si renderizaba dos veces seguidas, la primera vez sin preselección <option>pero la segunda vez con una, la <select>etiqueta no se actualiza en la segunda representación, sino que permanece en la predeterminada primero.

Encontré una solución para esto usando referencias . Debe obtener una referencia a su <select>nodo de etiqueta (que podría estar anidado en algún componente) y luego actualizar manualmente la valuepropiedad en él, en el componentDidUpdategancho.

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

Publicando una respuesta similar para 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
fuente
0

Tengo una solución simple es seguir el HTML básico.

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

.text-hide es una clase de bootstrap, si no usa bootstrap, aquí está:

.text-hide {
  font: 0/0 a;
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}
finlandés
fuente
-1

Resolví un problema similar estableciendo defaultProps:

ComponentName.defaultProps = {
  propName: ''
}

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

Así que ahora evito errores en la compilación si mi accesorio no existe hasta el montaje.

Matt Saunders
fuente
Eso realmente no está resolviendo el problema. Obtendrá esto: Advertencia: tipo de accesorio fallido: proporcionó un valueaccesorio a un campo de formulario sin un onChangecontrolador. Esto generará un campo de solo lectura. Si el campo debe ser mutable, use defaultValue. De lo contrario, establezca onChangeo readOnly.
Jason Rice