<select>
El componente nativo del navegador <select>
te permite renderizar un recuadro select con opciones.
<select>
<option value="someOption">Una opción</option>
<option value="otherOption">Otra opción</option>
</select>
Referencia
<select>
Para mostrar un recuadro de selección, renderiza el componente nativo del navegador <select>
.
<select>
<option value="someOption">Una opción</option>
<option value="otherOption">Otra opción</option>
</select>
Props
<select>
soporta todos los elementos prop comunes.
Puedes hacer un recuadro de selección controlado al pasar una prop value
:
value
: Un string (o un array de strings paramultiple={true}
). Controla qué opción se ha seleccionado. Cada valor de string coincide con elvalue
de alguna<option>
anidada dentro del<select>
.
Cuando pases un value
, tienes que incluir también un handler onChange
que actualice el valor que has pasado.
Si tu <select>
es no controlado, deberías incluir en su lugar la prop defaultValue
:
defaultValue
: Un string (o un array de strings paramultiple={true}
). Especifica la opción inicial seleccionada.
Estas props del <select>
son relevantes tanto para recuadros de selección no controlados como controlados:
autoComplete
: Un string. Especifica uno de los posibles comportamientos de autocompletado.autoFocus
: Un booleano. Si estrue
, React enfocará el elemento en su montaje.children
:<select>
acepta<option>
,<optgroup>
y el componente<datalist>
como children. También puedes pasarle tus propios componentes siempre y cuando ellos rendericen eventualmente uno de los componentes aceptados. Si pasas tus propios componentes que eventualmente rendericen la etiqueta<option>
, cada<option>
que renderices debe tener unvalue
.disabled
: Un booleano. Si estrue
, el recuadro de selección no será interactivo y aparecerá atenuado.form
: Un string. Especifica elid
del<form>
al que pertenece este recuadro de selección. Si se omite, es al form padre más próximo.multiple
: Un booleano. Si estrue
, el navegador permite selección múltiple.name
: Un string. Especifica el nombre de este recuadro de selección que será enviado con el submit del form.onChange
: Una funciónEvent
handler. Necesaria para los recuadros de selección controlados. Se ejecuta inmediatamente cuando el usuario elige una opción diferente. Se comporta como el eventoinput
del navegador.onChangeCapture
: Una versión deonChange
que se ejecuta en la fase de captura.onInput
: Una funciónEvent
handler. Se ejecuta inmediatamente cuando el valor es cambiado por el usuario. Por razones históricas, en React es propio al lenguaje usaronChange
en su lugar que funciona de forma similar.onInputCapture
: Una versión deonInput
que se ejecuta en la fase de captura.onInvalid
: Una funciónEvent
handler. Se ejecuta si un input falla en la validación en el envío de un formulario. A diferencia del evento nativoinvalid
, el eventoonInvalid
de React se propaga.onInvalidCapture
: Una versión deonInvalid
que se ejecuta en la fase de captura.required
: Un booleano. Si estrue
, el valor tiene que ser incluido por el formulario para que se envíe.size
: Un número. Para selecciones demultiple={true}
, especifica el número escogido de elementos visibles inicialmente.
Advertencias
- A diferencia de en HTML, pasar un atributo
selected
a<option>
no está soportado. En su lugar, usa<select defaultValue>
para recuadros de selección no controlados y<select value>
para recuadros de selección controlados. - Si un recuadro de selección recibe una prop
value
será tratado como controlado. - Un recuadro de selección no puede ser controlado y no controlado al mismo tiempo.
- Un recuadro de selección no puede cambiar entre controlado y no controlado durante su ciclo de vida.
- Cada recuadro de selección necesita un event handler
onChange
que actualice de forma síncrona su valor permitido.
Uso
Muestra un recuadro de selección con opciones
Renderiza un <select>
con una lista de componentes <option>
dentro para mostrar un recuadro de selección. Da a cada <option>
un value
representando los datos que serán enviados en el envío del formulario.
export default function FruitPicker() { return ( <label> Elige una fruta: <select name="selectedFruit"> <option value="apple">Manzana</option> <option value="banana">Plátano</option> <option value="orange">Naranja</option> </select> </label> ); }
Incluir una label para un recuadro de selección
De forma típica, incluirás cada <select>
dentro de una etiqueta <label>
. Esto indica al navegador que esta label está asociada con ese recuadro de selección. Cuando el usuario hace click en la label, el navegador automáticamente enfocará el recuadro de selección. También es esencial para la accesibilidad: un lector de pantalla reproducirá la leyenda de esa label cuando el usuario enfoque el recuadro de selección.
Si no puedes anidar un <select>
en una <label>
, asócialos al pasarles el mismo ID a <select id>
y a <label htmlFor>
. Para evitar conflictos entre múltiples instancias de un componente, genera ese ID usando useId
.
import { useId } from 'react'; export default function Form() { const vegetableSelectId = useId(); return ( <> <label> Elige una fruta: <select name="selectedFruit"> <option value="apple">Manzana</option> <option value="banana">Plátano</option> <option value="orange">Naranja</option> </select> </label> <hr /> <label htmlFor={vegetableSelectId}> Elige una verdura: </label> <select id={vegetableSelectId} name="selectedVegetable"> <option value="cucumber">Pepino</option> <option value="corn">Maíz</option> <option value="tomato">Tomate</option> </select> </> ); }
Incluir una opción inicial seleccionada
Por defecto, el navegador seleccionará el primer <option>
de la lista. Para seleccionar otra opción distinta por defecto, incluye ese value
del <option>
como el defaultValue
para el elemento <select>
.
export default function FruitPicker() { return ( <label> Elige una fruta: <select name="selectedFruit" defaultValue="orange"> <option value="apple">Manzana</option> <option value="banana">Plátano</option> <option value="orange">Naranja</option> </select> </label> ); }
Permitir la selección múltiple
Pasa multiple={true}
al <select>
para permitir al usuario seleccionar múltiples opciones. En ese caso, si también especificas un defaultValue
para escoger la opción inicial seleccionada, debe ser un array.
export default function FruitPicker() { return ( <label> Elige algunas frutas: <select name="selectedFruit" defaultValue={['orange', 'banana']} multiple={true} > <option value="apple">Manzana</option> <option value="banana">Plátano</option> <option value="orange">Naranja</option> </select> </label> ); }
Leer el valor del recuadro de selección al enviar un formulario
Añade un <form>
que envuelve tu recuadro de selección con un <button type="submit">
dentro. Llamará a tu event handler <form onSubmit>
. Por defecto, el navegador enviará los datos del formulario a el URL actual y recargará la página. Puedes sobreescribir este comportamiento llamando a e.preventDefault()
. Lee los datos del formulario con new FormData(e.target)
.
export default function EditPost() { function handleSubmit(e) { // Evita que el navegador recargue la página e.preventDefault(); // Lee los datos del formulario const form = e.target; const formData = new FormData(form); // Puedes pasar formData como cuerpo del fetch directamente: fetch('/some-api', { method: form.method, body: formData }); // Puedes generar una URL de él, como hace el navegador por defecto: console.log(new URLSearchParams(formData).toString()); // Puedes trabajar con él como un objeto plano. const formJson = Object.fromEntries(formData.entries()); console.log(formJson); // (!) Esto no incluye múltiples valores de selección // O puedes obtener un array de pares name-value. console.log([...formData.entries()]); } return ( <form method="post" onSubmit={handleSubmit}> <label> Elige tu fruta favorita: <select name="selectedFruit" defaultValue="orange"> <option value="apple">Manzana</option> <option value="banana">Plátano</option> <option value="orange">Naranja</option> </select> </label> <label> Elige todas tus verduras favoritas: <select name="selectedVegetables" multiple={true} defaultValue={['corn', 'tomato']} > <option value="cucumber">Pepino</option> <option value="corn">Maíz</option> <option value="tomato">Tomate</option> </select> </label> <hr /> <button type="reset">Reset</button> <button type="submit">Submit</button> </form> ); }
Controlar un recuadro de selección con una variable de estado
Un recuadro de selección como <select />
es no controlado. Incluso si incluyes un valor seleccionado inicialmente como <select defaultValue="orange" />
, tu JSX sólo especifica el valor inicial, no su valor ahora mismo.
Para renderizar un recuadro de selección controlado, añádele su prop value
. React forzará al recuadro de selección para tener siempre el value
que pasaste. De forma típica, controlarás un recuadro de selección declarando una variable de estado:
function FruitPicker() {
const [selectedFruit, setSelectedFruit] = useState('orange'); // Declara una variable de estado,...
// ...
return (
<select
value={selectedFruit} // ...fuerza al valor del select a coincidir con la variable de estado,...
onChange={e => setSelectedFruit(e.target.value)} // ...¡y a actualizar la variable de estado con cualquier cambio!
>
<option value="apple">Manzana</option>
<option value="banana">Plátano</option>
<option value="orange">Naranja</option>
</select>
);
}
Esto es útil si quieres volver a renderizar alguna parte de la UI en respuesta a cada selección.
import { useState } from 'react'; export default function FruitPicker() { const [selectedFruit, setSelectedFruit] = useState('orange'); const [selectedVegs, setSelectedVegs] = useState(['corn', 'tomato']); return ( <> <label> Elige una fruta: <select value={selectedFruit} onChange={e => setSelectedFruit(e.target.value)} > <option value="apple">Manzana</option> <option value="banana">Plátano</option> <option value="orange">Naranja</option> </select> </label> <hr /> <label> Elige todas tus verduras favoritas: <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">Maíz</option> <option value="tomato">Tomate</option> </select> </label> <hr /> <p>Tu fruta favorita: {selectedFruit}</p> <p>Tus verduras favoritas: {selectedVegs.join(', ')}</p> </> ); }