– React (original) (raw)

The built-in browser component lets you render a select box with options.


<select>

<option value="someOption">Some option</option>

<option value="otherOption">Other option</option>

</select>


Reference

<select>

To display a select box, render the built-in browser component.


<select>

<option value="someOption">Some option</option>

<option value="otherOption">Other option</option>

</select>

See more examples below.

Props

<select> supports all common element props.

You can make a select box controlled by passing a value prop:

When you pass value, you must also pass an onChange handler that updates the passed value.

If your <select> is uncontrolled, you may pass the defaultValue prop instead:

These <select> props are relevant both for uncontrolled and controlled select boxes:

Caveats


Usage

Displaying a select box with options

Render a <select> with a list of <option> components inside to display a select box. Give each <option> a value representing the data to be submitted with the form.


Providing a label for a select box

Typically, you will place every <select> inside a tag. This tells the browser that this label is associated with that select box. When the user clicks the label, the browser will automatically focus the select box. It’s also essential for accessibility: a screen reader will announce the label caption when the user focuses the select box.

If you can’t nest <select> into a <label>, associate them by passing the same ID to <select id> and . To avoid conflicts between multiple instances of one component, generate such an ID with useId.

import { useId } from 'react';

export default function Form() { const vegetableSelectId = useId(); return ( <> Pick a fruit:


Pick a vegetable: </> ); }


Providing an initially selected option

By default, the browser will select the first <option> in the list. To select a different option by default, pass that <option>’s value as the defaultValue to the <select> element.

Pitfall

Unlike in HTML, passing a selected attribute to an individual <option> is not supported.


Enabling multiple selection

Pass multiple={true} to the <select> to let the user select multiple options. In that case, if you also specify defaultValue to choose the initially selected options, it must be an array.

export default function FruitPicker() { return ( Pick some fruits: <select name="selectedFruit" defaultValue={['orange', 'banana']} multiple={true} > ); }


Reading the select box value when submitting a form

Add a around your select box with a inside. It will call your <form onSubmit> event handler. By default, the browser will send the form data to the current URL and refresh the page. You can override that behavior by calling e.preventDefault(). Read the form data with new FormData(e.target).

export default function EditPost() { function handleSubmit(e) {

e.preventDefault();

const form = e.target;
const formData = new FormData(form);

fetch('/some-api', { method: form.method, body: formData });

console.log(new URLSearchParams(formData).toString());

const formJson = Object.fromEntries(formData.entries());
console.log(formJson); 

console.log([...formData.entries()]);

}

return (

Pick your favorite fruit: Pick all your favorite vegetables: <select name="selectedVegetables" multiple={true} defaultValue={['corn', 'tomato']} >
Reset Submit ); }

Note

Give a name to your <select>, for example <select name="selectedFruit" />. The name you specified will be used as a key in the form data, for example { selectedFruit: "orange" }.

If you use <select multiple={true}>, the FormData you’ll read from the form will include each selected value as a separate name-value pair. Look closely at the console logs in the example above.

Pitfall

By default, any <button> inside a <form> will submit it. This can be surprising! If you have your own custom Button React component, consider returning instead of <button>. Then, to be explicit, use <button type="submit"> for buttons that are supposed to submit the form.


Controlling a select box with a state variable

A select box like <select /> is uncontrolled. Even if you pass an initially selected value like <select defaultValue="orange" />, your JSX only specifies the initial value, not the value right now.

To render a controlled select box, pass the value prop to it. React will force the select box to always have the value you passed. Typically, you will control a select box by declaring a state variable:


function FruitPicker() {

const [selectedFruit, setSelectedFruit] = useState('orange'); // Declare a state variable...

// ...

return (

<select

value={selectedFruit} // ...force the select's value to match the state variable...

onChange={e => setSelectedFruit(e.target.value)} // ... and update the state variable on any change!

>

<option value="apple">Apple</option>

<option value="banana">Banana</option>

<option value="orange">Orange</option>

</select>

);

}

This is useful if you want to re-render some part of the UI in response to every selection.

import { useState } from 'react';

export default function FruitPicker() { const [selectedFruit, setSelectedFruit] = useState('orange'); const [selectedVegs, setSelectedVegs] = useState(['corn', 'tomato']); return ( <> Pick a fruit: <select value={selectedFruit} onChange={e => setSelectedFruit(e.target.value)} >


Pick all your favorite vegetables: <select multiple={true} value={selectedVegs} onChange={e => { const options = [...e.target.selectedOptions]; const values = options.map(option => option.value); setSelectedVegs(values); }} >

Your favorite fruit: {selectedFruit}

Your favorite vegetables: {selectedVegs.join(', ')}

</> ); }

Pitfall

If you pass value without onChange, it will be impossible to select an option. When you control a select box by passing some value to it, you force it to always have the value you passed. So if you pass a state variable as a value but forget to update that state variable synchronously during the onChange event handler, React will revert the select box after every keystroke back to the value that you specified.

Unlike in HTML, passing a selected attribute to an individual <option> is not supported.