# How to Build a React Drop Down Component: Controlled and Uncontrolled Select Patterns

> Learn to build a React drop down component using controlled and uncontrolled patterns. Display options effectively by managing state or default values.

- Repository: [Meta/react](https://github.com/facebook/react)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Implement a React drop down component by rendering a native `<select>` element with `<option>` children, managing the selected value through React state for controlled components or using `defaultValue` for uncontrolled components.**

A React drop down component leverages the standard HTML `<select>` element while integrating with React's state management system. According to the facebook/react source code, React treats `<select>` like any other DOM element but adds controlled-component semantics that synchronize the selected value with your component state.

## Understanding Controlled vs Uncontrolled React Drop Down Components

React supports two fundamental patterns for managing form inputs, including drop down components. The choice between controlled and uncontrolled determines where the source of truth for the selected value resides.

### Controlled Components

In a controlled React drop down component, the selected value is stored in React state and updated via the `onChange` handler. The `useState` hook, defined in [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js), creates the state primitive that survives re-renders. React writes the `value` prop to the DOM during every render cycle, ensuring the UI always reflects the current state.

### Uncontrolled Components

An uncontrolled React drop down component stores the selected value in the DOM itself. You provide a `defaultValue` prop to set the initial selection, after which the browser manages subsequent changes. The test suite in [`packages/react-dom/src/__tests__/ReactDOMSelect-test.js`](https://github.com/facebook/react/blob/main/packages/react-dom/src/__tests__/ReactDOMSelect-test.js) documents this behavior, showing how React writes the default value once during the initial mount and then relinquishes control to the browser.

## Building a Controlled React Drop Down Component

The controlled pattern is the recommended approach for most React applications because it enables you to validate, transform, or persist the selected value before it reaches the UI.

```jsx
import React from 'react';

function Dropdown({ options, initial = '' }) {
  const [value, setValue] = React.useState(initial);

  const handleChange = (e) => {
    setValue(e.target.value);
  };

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

export default function App() {
  const colors = ['Red', 'Green', 'Blue'];
  return (
    <div>
      <h2>Select a color</h2>
      <Dropdown options={colors} initial="Green" />
    </div>
  );
}

```

This implementation uses `useState` from [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js) to maintain the selection state. The `value` prop forces React to keep the DOM synchronized with the state on every render, while `onChange` captures user interactions through React's synthetic event system.

## Creating an Uncontrolled React Drop Down Component

Use the uncontrolled pattern when you need minimal React intervention or are integrating with non-React code.

```jsx
import React from 'react';

function UncontrolledDropdown({ options, defaultValue = '' }) {
  return (
    <select defaultValue={defaultValue}>
      {options.map((opt) => (
        <option key={opt} value={opt}>
          {opt}
        </option>
      ))}
    </select>
  );
}

export function App() {
  const fruits = ['Apple', 'Banana', 'Cherry'];
  return (
    <div>
      <h2>Pick a fruit (uncontrolled)</h2>
      <UncontrolledDropdown options={fruits} defaultValue="Banana" />
    </div>
  );
}

```

As verified in [`packages/react-dom/src/__tests__/ReactDOMSelect-test.js`](https://github.com/facebook/react/blob/main/packages/react-dom/src/__tests__/ReactDOMSelect-test.js), React writes the `defaultValue` to the DOM during the initial mount and then allows the browser to manage subsequent user interactions without React state updates.

## Implementing a Multi-Select React Drop Down Component

React supports multi-select drop downs by passing an array to the `value` prop and using the `multiple` attribute.

```jsx
import React from 'react';

function MultiSelect({ options, initial = [] }) {
  const [selected, setSelected] = React.useState(initial);

  const handleChange = (e) => {
    const values = Array.from(e.target.selectedOptions, (opt) => opt.value);
    setSelected(values);
  };

  return (
    <select multiple value={selected} onChange={handleChange}>
      {options.map((opt) => (
        <option key={opt} value={opt}>
          {opt}
        </option>
      ))}
    </select>
  );
}

export function App() {
  const planets = ['Mercury', 'Venus', 'Earth', 'Mars'];
  return (
    <div>
      <h2>Choose planets</h2>
      <MultiSelect options={planets} initial={['Earth', 'Mars']} />
    </div>
  );
}

```

The `multiple` attribute tells the browser to allow multiple selections. React synchronizes the array of selected values through the `value` prop, reading selections from `event.target.selectedOptions` as documented in the synthetic event system tests.

## Key Implementation Files in the React Source Code

Understanding the underlying React architecture helps explain why these patterns work. The facebook/react repository contains the authoritative implementations:

- **[`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js)** – Defines `useState` and other hook primitives that enable stateful React drop down components to persist selection values across renders.

- **[`packages/react-dom/src/__tests__/ReactDOMSelect-test.js`](https://github.com/facebook/react/blob/main/packages/react-dom/src/__tests__/ReactDOMSelect-test.js)** – Contains the test suite that specifies expected behavior for `<select>` elements in both controlled and uncontrolled modes, including `value` and `defaultValue` handling.

- **[`packages/react-dom/src/events/plugins/__tests__/SelectEventPlugin-test.js`](https://github.com/facebook/react/blob/main/packages/react-dom/src/events/plugins/__tests__/SelectEventPlugin-test.js)** – Documents the synthetic `select` event that React dispatches when users interact with drop down components, enabling custom `onChange` handling.

## Summary

- A **React drop down component** renders a standard `<select>` element with `<option>` children, managed through React's component model.
- **Controlled components** store the selected value in React state using `useState` (defined in [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js)) and synchronize via the `value` prop.
- **Uncontrolled components** use `defaultValue` to set an initial selection, after which the browser manages the value, as verified in [`packages/react-dom/src/__tests__/ReactDOMSelect-test.js`](https://github.com/facebook/react/blob/main/packages/react-dom/src/__tests__/ReactDOMSelect-test.js).
- **Multi-select** drop downs pass an array to the `value` prop and read `event.target.selectedOptions` to handle multiple selections.
- React's synthetic event system dispatches `onChange` events for drop down interactions, documented in the SelectEventPlugin test suite.

## Frequently Asked Questions

### What is the difference between controlled and uncontrolled select in React?

A controlled React drop down component uses the `value` prop and `onChange` handler to store the selection in React state, giving you programmatic control over the current value. An uncontrolled component uses `defaultValue` to set the initial selection, after which the browser manages the value internally without React state updates, as implemented in the React DOM reconciler and tested in [`ReactDOMSelect-test.js`](https://github.com/facebook/react/blob/main/ReactDOMSelect-test.js).

### How do I handle multiple selections in a React drop down?

Add the `multiple` attribute to your `<select>` element and pass an array of selected values to the `value` prop. In your `onChange` handler, extract the selected options using `Array.from(event.target.selectedOptions).map(opt => opt.value)` to update your state array. React synchronizes this array with the DOM during each render cycle.

### Where does React implement the select element behavior?

React implements `<select>` element behavior in the React DOM package, specifically within the reconciler logic that handles form elements. The authoritative reference for this behavior is the test file [`packages/react-dom/src/__tests__/ReactDOMSelect-test.js`](https://github.com/facebook/react/blob/main/packages/react-dom/src/__tests__/ReactDOMSelect-test.js), which defines how `value`, `defaultValue`, and `multiple` attributes should interact with the DOM. The `useState` hook used to manage select values is defined in [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js).

### Should I use controlled or uncontrolled components for forms?

Use **controlled components** when you need to validate, transform, or persist form data before it reaches the UI, or when multiple UI elements need to stay synchronized with the same data. Use **uncontrolled components** when integrating with non-React code, when you need minimal React intervention for simple forms, or when using file inputs that cannot be controlled due to browser security restrictions. For most React applications, controlled components provide more predictable data flow and easier testing.