Reagir JSX: selecionando "selecionado" na opção <selecionar> selecionada


403

Em um componente React para um <select>menu, preciso definir o selectedatributo na opção que reflete o estado do aplicativo.

Em render(), o optionStateé passado do proprietário do estado para o componente SortMenu. Os valores da opção são transmitidos a partir propsdo 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

No entanto, isso dispara um erro de sintaxe na compilação JSX.

Fazer isso se livra do erro de sintaxe, mas obviamente não resolve o problema:

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

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

Eu também tentei isso:

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

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

Existe uma maneira recomendada de resolver isso?


Upvoting a pergunta apenas para o título
ericgio

Respostas:


649

O React compreende automaticamente os booleanos para esse fim, para que você possa simplesmente escrever (nota: não recomendado)

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

e produzirá 'selecionado' adequadamente.

No entanto, o React torna isso ainda mais fácil para você. Em vez de definir selectedcada opção, você pode (e deve) simplesmente escrever value={optionsState}na própria tag select :

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

Para mais informações, consulte o documento React select tag .


56
Com a versão atual do React (0.9), a configuração do atributo selecionado nas opções não funciona. Defina o atributo value no elemento select.
Liammclennan

2
eu carrego dados com ajax.defaultValue não está funcionando para mim. O valor está funcionando, mas eu não posso selecionar outro item na lista de seleção. A lista está abrindo, mas quando eu seleciono um deles, selecione o item de valor.
User1924375

5
@ user1924375 você deve usar o evento onChange onChange={this.handleSelect}e definir o valor do estado do seu componente, por exemplo: 'handleSelect: function () {this.setState ({value: event.target.value});} `Isso renderia novamente o componente selecionado com novos item selecionado. Espero que isso ajude você.
funnydaredevil

11
Embora ainda não esteja documentado, o valuesuporte em um <select>pode ser uma matriz, se você tiver multiselectativado.
precisa saber é

4
Em vez disso, use defaultValuepara inicializar
dewwwald 4/17/17

70

Você pode fazer o que o React avisa quando tenta definir a propriedade "selecionada" do <option>:

Use o defaultValueou valueadereços em <select>vez de configuração selectedon <option>.

Então, você pode usar options.valueno defaultValueseu


9
Se eu ainda quiser indicar a opção atualmente selecionada, como eu faria isso? Atualmente, a única maneira de manter a opção selecionada (e manter o estado do formulário para futuras postagens) é definindo select = true. Tentei definir os adereços defaultValue e value do elemento select, mas isso não é renderizado na exibição, definindo a opção correta para selecionada no menu de opções. Algum conselho?
The Pied Pipes

4
Exemplo talvez ??
Shinzou 11/0618

11
Não está funcionando para mim: <select className = "form-control" value = "Mois">
Kuartz 07/07/19

2
defaultValue não funciona com a versão mais recente
Hos Mercury

18

Aqui está uma solução completa que incorpora a melhor resposta e os comentários abaixo (o que pode ajudar alguém que está lutando para juntar tudo):

ATUALIZAÇÃO PARA ES6 (2019) - usando funções de seta e destruição de objeto

no 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 incluído (que agora é um funcional sem 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>
)

RESPOSTA ANTERIOR (usando ligação):

no 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 incluído (que agora é um funcional sem 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>
)

o componente principal mantém o valor selecionado para a fruta (no estado), o componente incluído exibe o elemento de seleção e as atualizações são passadas de volta ao componente principal para atualizar seu estado (que volta ao componente incluído para alterar o valor selecionado).

Observe o uso de um nome prop que permite declarar um único método handleChange para outros campos no mesmo formulário, independentemente do tipo.


Observe que a linha no construtor this.handleChange.bind(this);deve ser this.handleChange = this.handleChange.bind(this);
Will Shaver

para aqueles de vocês como eu, que pedindo-lhes auto Que ... meios: reactjs.org/docs/jsx-in-depth.html#spread-attributes
talsibony

@talsibony - esse é realmente o operador de propagação, mas no meu código de exemplo significa apenas inserir outro código aqui !
Andy Lorenz

@AndyLorenz Então, nesse caso eu recomendo para removê-lo ... :), ou um comentário basta escrever como // resto do seu código
talsibony

8

Aqui está o exemplo mais recente de como fazê-lo. Dos documentos de reação , além da sintaxe do método "fat-arrow" de ligação automática.

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

Basta adicionar como primeira opção a sua tag de seleção:

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

Isso se tornará padrão e, quando você selecionar uma opção válida, será definida em seu estado


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

11
Embora nenhuma explicação tenha sido dada, uma não era realmente necessária. As várias maneiras de abordar o mesmo problema foram informações realmente úteis. Graças
DJ2

0

Ocorreu um problema com as <select>tags que não foram atualizadas corretamente <option>quando o estado muda. Meu problema parecia ser que, se você renderizar duas vezes em rápida sucessão, na primeira vez sem pré-selecionado, <option>mas na segunda vez com um, a <select>tag não será atualizada na segunda renderização, mas permanecerá no padrão primeiro.

Eu encontrei uma solução para isso usando refs . Você precisa obter uma referência ao seu <select>nó de tag (que pode estar aninhado em algum componente) e, em seguida, atualizar manualmente a valuepropriedade nele, no componentDidUpdategancho.

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

0

Postando uma resposta semelhante 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>
  )
}

0

Eu tenho uma solução simples é seguir o 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 é uma classe de bootstrap, se você não estiver usando o bootstrap, aqui está:

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

-1

Eu resolvi um problema semelhante ao definir defaultProps:

ComponentName.defaultProps = {
  propName: ''
}

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

Portanto, agora evito erros na compilação se meu suporte não existir até a montagem.


Isso realmente não está resolvendo o problema. Você receberá: Aviso: Tipo de suporte com falha: você forneceu um valuesuporte a um campo de formulário sem um onChangemanipulador. Isso renderizará um campo somente leitura. Se o campo deve ser mutável, use defaultValue. Caso contrário, defina onChangeou readOnly.
Jason Rice
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.