O componente <select> nativo do navegador permite que você renderize uma caixa de seleção com opções.

<select>
<option value="someOption">Alguma opção</option>
<option value="otherOption">Outra opção</option>
</select>

Referência

<select>

Para exibir uma caixa de seleção, renderize o componente <select> nativo do navegador.

<select>
<option value="someOption">Alguma opção</option>
<option value="otherOption">Outra opção</option>
</select>

Veja mais exemplos abaixo.

Props

<select> suporta todas as props de elementos gerais.

Você pode tornar uma caixa de seleção controlada passando a prop value:

  • value: Uma string (ou um array de strings para multiple={true}). Controla qual opção está selecionada. Cada valor de string corresponde ao value de algum <option> aninhado dentro do <select>.

Ao passar value, você deve também passar o manipulador onChange que atualize o valor passado.

Se o <select> for não controlado, você pode passar a prop defaultValue em vez disso:

Essas props <select> são relevantes tanto para caixas de seleção controladas e não controladas:

  • autoComplete: Uma string. Especifica um dos possíveis comportamentos de preenchimento automático.
  • autoFocus: Um booleano. Se true, o React irá focar o elemento ao montar.
  • children: <select> aceita os componentes <option>, <optgroup> e <datalist> como filhos. Você também pode passar seus próprios componentes, desde que eventualmente renderizam um dos componentes permitidos. Se passar seus próprios componentes, que eventualmente renderizem tags <option>, cada <option> que você renderize precisa ter um value.
  • disabled: Um booleano. Se true, a caixa de seleção não será interativa e aparecerá desativada.
  • form: Uma string. Especifica o id do <form> ao qual esta caixa de seleção pertence. Se omitido, será o formulário pai mais próximo.
  • multiple: Um booleano. If true, o navegador permite seleção múltipla.
  • name: Uma string. Especifica o nome desta caixa de seleção que é enviado com o formulário.
  • onChange: Uma função de manipulador de Event. Necessário para caixas de seleção controladas. Dispara imediatamente quando o usuário escolhe uma opção diferente. Se comporta como o evento de input do navegador.
  • onChangeCapture: Uma versão de onChange que dispara na fase de captura.
  • onInput: Uma função de manipulador de Event. Dispara imediatamente quando o valor é alterado pelo usuário. Por razões históricas, é comum usar onChange no React, que funciona de forma similar.
  • onInputCapture: Uma versão de onInput que dispara na fase de captura.
  • onInvalid: Uma função de manipulador de Event. Dispara se uma entrada falha na validação ao enviar o formulário. Diferente do evento invalid nativo, o evento onInvalid do React é propagado.
  • onInvalidCapture: Uma versão de onInvalid que dispara na fase de captura.
  • required: Um booleano. Se true, o valor deve ser fornecido para o envio do formulário.
  • size: Um número. Para selects multiple={true} selects, especifica o número preferencial de itens visíveis inicialmente.

Ressalvas

  • Diferente do HTML, passar um atributo selected para <option> não é suportado. Em vez disso, use <select defaultValue> para caixas de seleção não controladas e <select value> para caixas de seleção controladas.
  • Se uma caixa de seleção receber a prop value, ela será tratada como controlada.
  • Uma caixa de seleção não pode ser simultaneamente controlada e não controlada.
  • Uma caixa de seleção não pode alternar entre ser controlada e não controlada durante sua vida útil.
  • Toda caixa de seleção controlada precisa de um manipulador de eventos onChange que atualize seu valor de forma síncrona.

Uso

Exibindo uma caixa de seleção com opções

Renderize um <select> com uma lista de componentes <option> dentro para exibir uma caixa de seleção. Dê a cada <option> um value que represente os dados a serem enviados com o formulário.

export default function FruitPicker() {
  return (
    <label>
      Escolha uma fruta:
      <select name="selectedFruit">
        <option value="apple">Maçã</option>
        <option value="banana">Banana</option>
        <option value="orange">Laranja</option>
      </select>
    </label>
  );
}


Fornecendo um rótulo para uma caixa de seleção

Normalmente, você colocará cada <select> dentro de uma tag <label>. Isso informa ao navegador que esse rótulo está associado a essa caixa de seleção. Quando o usuário clica no rótulo, o navegador automaticamente foca na caixa de seleção. Isso também é essencial para acessibilidade: um leitor de tela anunciará a legenda do rótulo quando o usuário focar na caixa de seleção.

Se não puder aninhar <select> dentro de um <label>, associe-os passando o mesmo ID para <select id> e <label htmlFor>. Para evitar conflitos entre múltiplas instâncias de um componente, gere um ID com useId.

import { useId } from 'react';

export default function Form() {
  const vegetableSelectId = useId();
  return (
    <>
      <label>
        Escolha uma fruta:
        <select name="selectedFruit">
          <option value="apple">Maçã</option>
          <option value="banana">Banana</option>
          <option value="orange">Laranja</option>
        </select>
      </label>
      <hr />
      <label htmlFor={vegetableSelectId}>
        Escolha um vegetal:
      </label>
      <select id={vegetableSelectId} name="selectedVegetable">
        <option value="cucumber">Pepino</option>
        <option value="corn">Milho</option>
        <option value="tomato">Tomate</option>
      </select>
    </>
  );
}


Fornecendo uma opção selecionada inicialmente

Por padrão, o navegador selecionará a primeira <option> na lista. Para selecionar uma opção diferente por padrão, passe o value dessa <option> como defaultValue para o elemento <select>.

export default function FruitPicker() {
  return (
    <label>
      Escolha uma fruta:
      <select name="selectedFruit" defaultValue="orange">
        <option value="apple">Maçã</option>
        <option value="banana">Banana</option>
        <option value="orange">Laranja</option>
      </select>
    </label>
  );
}

Pitfall

Diferente do HTML, passar um atributo selected para uma <option> individual não é suportado.


Habilitando seleção múltipla

Passe multiple={true} para o <select> para permitir que o usuário selecione várias opções. Nesse caso, se você também especificar defaultValue para escolher as opções selecionadas inicialmente, ele deve ser um array.

export default function FruitPicker() {
  return (
    <label>
      Escolha algumas frutas:
      <select
        name="selectedFruit"
        defaultValue={['orange', 'banana']}
        multiple={true}
      >
        <option value="apple">Maçã</option>
        <option value="banana">Banana</option>
        <option value="orange">Laranja</option>
      </select>
    </label>
  );
}


Lendo o valor da caixa de seleção ao enviar um formulário

Adicione um <form> em torno da sua caixa de seleção com um <button type="submit"> dentro. Isso chamará o manipulador de evento <form onSubmit>. Por padrão, o navegador enviará os dados do formulário para a URL atual e recarregará a página. Você pode substituir esse comportamento chamando e.preventDefault(). Leia os dados do formulário com new FormData(e.target).

export default function EditPost() {
  function handleSubmit(e) {
    // Impede o navegador de recarregar a página
    e.preventDefault();
    // Lê os dados do formulário
    const form = e.target;
    const formData = new FormData(form);
    // Você pode passar formData diretamente como corpo de uma requisição fetch:
    fetch('/some-api', { method: form.method, body: formData });
    // Você pode gerar uma URL a partir disso, como o navegador faz por padrão:
    console.log(new URLSearchParams(formData).toString());
    // Você pode trabalhar com isso como um objeto simples.
    const formJson = Object.fromEntries(formData.entries());
    console.log(formJson); // (!) Isso não inclui valores de seleção múltipla
    // Ou você pode obter um array de pares de nome e valor.
    console.log([...formData.entries()]);
  }

  return (
    <form method="post" onSubmit={handleSubmit}>
      <label>
        Escolha sua fruta favorita:
        <select name="selectedFruit" defaultValue="orange">
          <option value="apple">Maçã</option>
          <option value="banana">Banana</option>
          <option value="orange">Laranja</option>
        </select>
      </label>
      <label>
        Escolha todos os seus vegetais favoritos:
        <select
          name="selectedVegetables"
          multiple={true}
          defaultValue={['corn', 'tomato']}
        >
          <option value="cucumber">Pepino</option>
          <option value="corn">Milho</option>
          <option value="tomato">Tomate</option>
        </select>
      </label>
      <hr />
      <button type="reset">Redefinir</button>
      <button type="submit">Enviar</button>
    </form>
  );
}

Note

Atribua um name ao seu <select>, por exemplo <select name="selectedFruit" />. O name que você especificou será usado como uma chave nos dados do formulário, por exemplo { selectedFruit: "orange" }.

Se você usar <select multiple={true}>, o FormData que você lerá do formulário incluirá cada valor selecionado como um par de nome e valor separado. Observe atentamente os logs do console no exemplo acima.

Pitfall

Por padrão, qualquer <button> dentro de um <form> irá submetê-lo. Isso pode ser surpreendente! Se você tiver seu próprio componente Button no React, considere retornar <button type="button"> em vez de <button>. Então, para ser explícito, use <button type="submit"> para botões que devem submeter o formulário.


Controlando uma caixa de seleção com uma variável de estado

Uma caixa de seleção como <select /> é não controlada. Mesmo se você passar um valor selecionado inicialmente como <select defaultValue="orange" />, seu JSX apenas especifica o valor inicial, não o valor atual.

Para renderizar uma caixa de seleção controlada, passe a prop value para ela. O React forçará a caixa de seleção a sempre ter o value que você passou. Normalmente, você controlará uma caixa de seleção declarando uma variável de estado:

function FruitPicker() {
const [selectedFruit, setSelectedFruit] = useState('orange'); // Declara uma variável de estado...
// ...
return (
<select
value={selectedFruit} // ...força o valor do select a coincidir com a variável de estado...
onChange={e => setSelectedFruit(e.target.value)} // ...e atualiza a variável de estado a cada alteração!
>
<option value="apple">Maçã</option>
<option value="banana">Banana</option>
<option value="orange">Laranja</option>
</select>
);
}

Isso é útil se você deseja re-renderizar alguma parte da interface em resposta a cada seleção.

import { useState } from 'react';

export default function FruitPicker() {
  const [selectedFruit, setSelectedFruit] = useState('orange');
  const [selectedVegs, setSelectedVegs] = useState(['corn', 'tomato']);
  return (
    <>
      <label>
        Escolha uma fruta:
        <select
          value={selectedFruit}
          onChange={e => setSelectedFruit(e.target.value)}
        >
          <option value="apple">Maçã</option>
          <option value="banana">Banana</option>
          <option value="orange">Laranja</option>
        </select>
      </label>
      <hr />
      <label>
        Escolha todos os seus vegetais favoritos:
        <select
          multiple={true}
          value={selectedVegs}
          onChange={e => {
            const options = [...e.target.selectedOptions];
            const values = options.map(option => option.value);
            setSelectedVegs(values);
          }}
        >
          <option value="cucumber">Pepino</option>
          <option value="corn">Milho</option>
          <option value="tomato">Tomate</option>
        </select>
      </label>
      <hr />
      <p>Sua fruta favorita: {selectedFruit}</p>
      <p>Seus vegetais favoritos: {selectedVegs.join(', ')}</p>
    </>
  );
}

Pitfall

Se você passar value sem onChange, será impossível selecionar uma opção. Quando você controla uma caixa de seleção, passando um value para ela, você força a caixa de seleção a sempre manter o valor passado. Portanto, se você passar uma variável de estado como value, mas esquecer de atualizar essa variável de estado de forma síncrona no manipulador de evento onChange, o React reverterá a caixa de seleção após cada tecla pressionada para o value que você especificou.

Diferente do HTML, passar um atributo selected para uma <option> individual não é suportado.