Como deixar uma option selecionada no React JS

Neste artigo você aprenderá a como deixar uma option selecionada no React JS, uma ação muito comum nos projetos web!

option selecionada no React JS capa

Fala programador(a), beleza? Bora aprender mais sobre React!

O controle de formulários é um aspecto essencial em muitas aplicações web.

Neste artigo, vamos explorar uma questão comum enfrentada por muitos desenvolvedores React: como deixar uma opção selecionada por padrão em um elemento select?

Se você está familiarizado com HTML, você pode se perguntar: “não posso apenas adicionar o atributo selected a uma opção?”

No React, no entanto, as coisas funcionam um pouco diferente. Vamos discutir o porquê e como lidar com isso.

O Elemento Select no React

Em HTML padrão, o atributo ‘selected’ é usado para definir a opção padrão em um elemento select. No React, no entanto, o valor do select é controlado pelo estado do componente.

Isso significa que o valor selecionado deve ser definido no estado do componente e depois vinculado ao elemento select.

Assim, o React controla o estado do elemento select, tornando-o um componente controlado.

Aqui está um exemplo básico de como um elemento select pode ser renderizado em um componente funcional React com Hooks:

import React, { useState } from 'react';

const SelectExample = () => {
  const [selectedOption, setSelectedOption] = useState('');

  const handleChange = (event) => {
    setSelectedOption(event.target.value);
  }

  return (
    <select value={selectedOption} onChange={handleChange}>
      <option value="">Selecione...</option>
      <option value="option1">Opção 1</option>
      <option value="option2">Opção 2</option>
      <option value="option3">Opção 3</option>
    </select>
  );
}

Definindo uma opção pré-selecionada

Se você deseja ter uma opção pré-selecionada quando o componente for renderizado, você pode simplesmente definir o estado inicial para o valor dessa opção.

Formação Claude Code
Formação Recomendada

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 45min

Aqui está como você pode fazer isso:

import React, { useState } from 'react';

const SelectExample = () => {
  const [selectedOption, setSelectedOption] = useState('option2');

  const handleChange = (event) => {
    setSelectedOption(event.target.value);
  }

  return (
    <select value={selectedOption} onChange={handleChange}>
      <option value="option1">Opção 1</option>
      <option value="option2">Opção 2</option>
      <option value="option3">Opção 3</option>
    </select>
  );
}

Neste exemplo, a opção “Opção 2” estará selecionada por padrão quando o componente for renderizado, porque o estado inicial ‘selectedOption’ é definido como ‘option2’.

Lidando com múltiplas opções selecionadas

Se você deseja permitir que múltiplas opções sejam selecionadas, você pode fazer isso alterando o elemento select para aceitar múltiplos valores e alterando o estado para armazenar um array de opções selecionadas.

import React, { useState } from 'react';

const SelectExample = () => {
  const [selectedOptions, setSelectedOptions] = useState(['option1', 'option2']);

  const handleChange = (event) => {
    const selected = Array.from(event.target.options)
      .filter(option => option.selected)
      .map(option => option.value);

    setSelectedOptions(selected);
  }

  return (
    <select multiple={true} value={selectedOptions} onChange={handleChange}>
      <option value="option1">Opção 1</option>
      <option value="option2">Opção 2</option>
      <option value="option3">Opção 3</option>
    </select>
  );
}

Neste exemplo, as opções ‘Opção 1’ e ‘Opção 2’ estarão selecionadas por padrão, porque o estado inicial ‘selectedOptions’ é definido como [‘option1’, ‘option2’].

Trabalhando com dados dinâmicos

Agora que temos uma compreensão básica de como deixar uma opção selecionada no React, é importante mencionar que muitas vezes você estará trabalhando com dados dinâmicos.

Por exemplo, as opções em seu elemento select podem ser originárias de uma chamada de API.

Nesse caso, o estado inicial pode não estar disponível imediatamente. Assim, o valor inicial do estado pode ser definido como null ou vazio, e então alterado uma vez que os dados estejam disponíveis.

import React, { useState, useEffect } from 'react';

const SelectExample = () => {
  const [selectedOption, setSelectedOption] = useState('');
  const [options, setOptions] = useState([]);

  useEffect(() => {
    // Simulando uma chamada de API
    setTimeout(() => {
      setOptions(['option1', 'option2', 'option3']);
      setSelectedOption('option2');
    }, 2000);
  }, []);

  const handleChange = (event) => {
    setSelectedOption(event.target.value);
  }

  return (
    <select value={selectedOption} onChange={handleChange}>
      {options.map((option, index) => <option key={index} value={option}>{option}</option>)}
    </select>
  );
}

Seleção de Opções Aninhadas

Outra situação comum é ter que gerenciar a seleção de opções aninhadas, onde a seleção de uma opção determina as opções disponíveis em uma seleção subsequente.

Neste caso, o estado inicial de ambas as seleções pode ser vazio e, em seguida, o estado da segunda seleção pode ser alterado com base na seleção da primeira.

import React, { useState } from 'react';

const SelectExample = () => {
  const [firstSelection, setFirstSelection] = useState('');
  const [secondSelection, setSecondSelection] = useState('');
  const [secondOptions, setSecondOptions] = useState([]);

  const firstOptions = ['option1', 'option2', 'option3'];

  const handleChangeFirst = (event) => {
    setFirstSelection(event.target.value);

    // Defina as opções de segunda seleção com base na primeira seleção
    switch (event.target.value) {
      case 'option1':
        setSecondOptions(['option1.1', 'option1.2']);
        break;
      case 'option2':
        setSecondOptions(['option2.1', 'option2.2']);
        break;
      case 'option3':
        setSecondOptions(['option3.1', 'option3.2']);
        break;
      default:
        setSecondOptions([]);
    }
  }

  const handleChangeSecond = (event) => {
    setSecondSelection(event.target.value);
  }

  return (
    <div>
      <select value={firstSelection} onChange={handleChangeFirst}>
        {firstOptions.map((option, index) => <option key={index} value={option}>{option}</option>)}
      </select>

      <select value={secondSelection} onChange={handleChangeSecond}>
        {secondOptions.map((option, index) => <option key={index} value={option}>{option}</option>)}
      </select>
    </div>
  );
}

Quer aprender mais sobre programação? Conheça nosso canal no YouTube:

Conclusão

Chegamos ao fim do artigo sobre como deixar a option selecionada no React JS!

A seleção de opções em um elemento select no React é um pouco diferente do que você pode estar acostumado com o HTML padrão, mas com a compreensão do conceito de componentes controlados, fica bastante simples.

Ao gerenciar o valor selecionado através do estado do componente, você pode ter um controle mais preciso sobre o comportamento do seu formulário, permitindo uma experiência de usuário mais fluida e reativa.

Está buscando em evoluir como Programador? Confira o nossos cursos de programação.

value ou defaultValue: qual dos dois usar?

Antes de sair codando, tem uma escolha que muda tudo no seu select

Se você só quer que uma option já venha marcada e não pretende ler nem mexer nesse valor por código, dá pra usar defaultValue no select e deixar o próprio navegador tomar conta

<select defaultValue="option2">
<option value="option1">Opção 1</option>
<option value="option2">Opção 2</option>
</select>

Agora, se você precisa ler o valor pra enviar num formulário, validar ou mudar a seleção por código, aí é value + onChange, o famoso componente controlado

Regra prática pra guardar: defaultValue é o "seleciona e me esquece", value é o "eu mando no select" 🙂

Tome cuidado! Não misture os dois no mesmo select, e nunca passe value sem onChange

Se você passar só o value, o select trava: o usuário clica, escolhe, e nada muda na tela, porque o estado nunca é atualizado (e o React ainda te avisa disso no console)

Por que a option não fica selecionada mesmo com o estado certo?

Esse é o bug que mais faz gente coçar a cabeça

O valor de uma option no DOM é SEMPRE texto

Então se o seu estado guarda um número vindo do banco, tipo 2, e a option tem value={2}, o React renderiza "2" e a comparação não bate do jeito que você espera

O resultado é o select voltando pra primeira opção como se você não tivesse setado nada

A solução é tratar tudo como string na tela e converter só na hora de salvar:

<select
value={String(selectedId)}
onChange={(e) => setSelectedId(Number(e.target.value))}
>
{categorias.map((c) => (
<option key={c.id} value={String(c.id)}>{c.nome}</option>
))}
</select>

Outro motivo comum pro select "não obedecer": o valor que você colocou no estado simplesmente não existe em nenhuma das options

Um espaço a mais, uma acentuação diferente, um id que veio como texto de um lado e número do outro, e pronto, o select não acha o par e cai no vazio

Faça o teste: dá um console.log no valor do estado e compare com o value das options renderizadas, é quase sempre isso…

Cuidados com a option pré-selecionada vinda de API:

Quando as options chegam depois, a ordem importa

Se você setar o valor selecionado ANTES das options existirem, o select renderiza vazio por um instante e pode não voltar sozinho

Então sete os dois no mesmo passo, como no exemplo acima, e só depois disso o valor tem onde "encaixar"

Outro detalhe que passa batido: usar o índice do array como key

Se a lista mudar de ordem ou for filtrada, as keys se embaralham e o React reaproveita elemento errado

Tendo um id, use ele:

{options.map((option) => (
<option key={option.id} value={option.id}>{option.nome}</option>
))}

E enquanto os dados não chegam, vale mostrar o select desabilitado ou uma option de carregando, pra ninguém clicar num campo vazio achando que quebrou

Placeholder que não pode ser escolhido:

Aquele "Selecione…" do primeiro exemplo tem um problema: ele é uma opção válida

O usuário pode voltar nele e enviar o formulário sem escolher nada

Pra evitar isso, deixe o placeholder desabilitado e marque o campo como obrigatório:

<select value={selectedOption} onChange={handleChange} required>
<option value="" disabled>Selecione...</option>
<option value="option1">Opção 1</option>
<option value="option2">Opção 2</option>
</select>

Com o estado iniciando em string vazia, o placeholder aparece, mas não dá pra voltar pra ele

E já que estamos aqui, amarre um label ao select, é o tipo de detalhe que melhora acessibilidade e ainda faz o clique no texto focar o campo:

<label htmlFor="categoria">Categoria</label>
<select id="categoria" value={selectedOption} onChange={handleChange}>

Pequeno, né? Mas é o que separa um formulário caprichado de um formulário "funciona e pronto" 😀

Um jeito mais curto de ler as selecionadas:

O Array.from(...).filter(...).map(...) funciona, mas o próprio elemento já te entrega só as marcadas

const handleChange = (event) => {
const selected = Array.from(event.target.selectedOptions, (o) => o.value);
setSelectedOptions(selected);
}

Mesmo resultado, uma linha

Se você passar string num select com multiple, nada fica marcado e você vai perder um tempão procurando o motivo… já me ferrei uma vez por causa disso haha

Duas coisas que mudaram desde que esse padrão virou padrão:

O conceito de componente controlado continua igualzinho, mas o contexto ao redor dele andou

Se o seu projeto usa componentes de servidor: um select controlado depende de estado, e estado só existe no cliente

Então o componente do formulário precisa ser um componente de cliente, senão o useState nem roda

É o erro que mais aparece quando alguém copia esse exemplo pra dentro de um projeto mais novo e leva um erro de hook logo de cara

Se o seu projeto usa TypeScript: o evento do select tem tipo próprio, e deixar ele solto como any derruba metade da vantagem de estar em TS


const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedOption(event.target.value);
}

Repare que é HTMLSelectElement, não HTMLInputElement

Troca boba, mas é a que mais aparece em código copiado de exemplo de input de texto 😛

Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares