Skip to content

Autocomplete

The Autocomplete component is a text input enhanced by a panel of suggested options.

Introduction

The autocomplete component is an enhanced text input that shows a list of suggested options as users type and lets them select an option from the list. It implements the WAI-ARIA Combobox pattern, and is typically used to assist users in completing form inputs or search queries faster.

Usage

After installation, you can start building with this hook as follows:

<span class="token keyword">import</span> useAutocomplete <span class="token keyword">from</span> <span class="token string">'@mui/base/useAutocomplete'</span><span class="token punctuation">;</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span>
    getRootProps<span class="token punctuation">,</span>
    getInputProps<span class="token punctuation">,</span>
    getListboxProps<span class="token punctuation">,</span>
    getOptionProps<span class="token punctuation">,</span>
    groupedOptions<span class="token punctuation">,</span>
  <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useAutocomplete</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'The Dark Knight'</span><span class="token punctuation">,</span> <span class="token literal-property property">year</span><span class="token operator">:</span> <span class="token number">2008</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'12 Angry Men'</span><span class="token punctuation">,</span> <span class="token literal-property property">year</span><span class="token operator">:</span> <span class="token number">1957</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">"Schindler's List"</span><span class="token punctuation">,</span> <span class="token literal-property property">year</span><span class="token operator">:</span> <span class="token number">1993</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token function-variable function">getOptionLabel</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">option</span><span class="token punctuation">)</span> <span class="token operator">=></span> option<span class="token punctuation">.</span>label<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token punctuation">(</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span></span><span class="token punctuation">></span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator">...</span><span class="token function">getRootProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator">...</span><span class="token function">getInputProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
      <span class="token punctuation">{</span>groupedOptions<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator">...</span><span class="token function">getListboxProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span>
          <span class="token punctuation">{</span>groupedOptions<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">option<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator">...</span><span class="token function">getOptionProps</span><span class="token punctuation">(</span><span class="token punctuation">{</span> option<span class="token punctuation">,</span> index <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span>option<span class="token punctuation">.</span>label<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
          <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span>
      <span class="token punctuation">)</span><span class="token punctuation">}</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span></span><span class="token punctuation">></span></span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

Basics

The useAutocomplete hook requires a list of options to be displayed when the textbox receives focus. The value must be chosen from a predefined set of values.

The following demo shows how to create a simple combobox, apply some styling, and write the selected value to a state variable using the onChange prop:

Press Enter to start editing

Customization

Rendering options

By default, the options prop accepts an array of strings or { label: string }:

<span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span> <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'The Godfather'</span><span class="token punctuation">,</span> <span class="token literal-property property">id</span><span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span> <span class="token literal-property property">label</span><span class="token operator">:</span> <span class="token string">'Pulp Fiction'</span><span class="token punctuation">,</span> <span class="token literal-property property">id</span><span class="token operator">:</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// or</span>
<span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'The Godfather'</span><span class="token punctuation">,</span> <span class="token string">'Pulp Fiction'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

If you need to use a different structure for options, you must provide a function to the getOptionLabel prop that resolves each option to a unique value.

<span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span> <span class="token literal-property property">issuer</span><span class="token operator">:</span> <span class="token string">'Bank of America'</span><span class="token punctuation">,</span> <span class="token literal-property property">brand</span><span class="token operator">:</span> <span class="token string">'Visa'</span><span class="token punctuation">,</span> <span class="token literal-property property">last4</span><span class="token operator">:</span> <span class="token string">'1234'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span> <span class="token literal-property property">issuer</span><span class="token operator">:</span> <span class="token string">'Bank of America'</span><span class="token punctuation">,</span> <span class="token literal-property property">brand</span><span class="token operator">:</span> <span class="token string">'MasterCard'</span><span class="token punctuation">,</span> <span class="token literal-property property">last4</span><span class="token operator">:</span> <span class="token string">'5678'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span> <span class="token literal-property property">issuer</span><span class="token operator">:</span> <span class="token string">'Barclays'</span><span class="token punctuation">,</span> <span class="token literal-property property">brand</span><span class="token operator">:</span> <span class="token string">'Visa'</span><span class="token punctuation">,</span> <span class="token literal-property property">last4</span><span class="token operator">:</span> <span class="token string">'4698'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token punctuation">{</span>
  getRootProps<span class="token punctuation">,</span>
  <span class="token comment">// etc</span>
<span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useAutocomplete</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token function-variable function">getOptionLabel</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">option</span><span class="token punctuation">)</span> <span class="token operator">=></span> option<span class="token punctuation">.</span>last4<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

Controlled states

The useAutocomplete hook has two states that can be controlled:

  1. the "value" state with the value/onChange props combination. This state represents the value selected by the user, for instance when pressing Enter.
  2. the "input value" state with the inputValue/onInputChange props combination. This state represents the value displayed in the textbox.
value: Firefox
inputValue: 

Using a portal

React Portals can be used to render the listbox outside of the DOM hierarchy, making it easier to allow it to "float" above adjacent elements.

Base UI provides a <Popper /> component built around React's createPortal() for exactly this purpose, and additionally helps you manage keyboard focus as it moves in and out of the portal.

To render the listbox in Base UI's Popper, the refs must be merged as follows:

<span class="token keyword">import</span> useAutocomplete <span class="token keyword">from</span> <span class="token string">'@mui/base/useAutocomplete'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> Popper <span class="token keyword">from</span> <span class="token string">'@mui/base/Popper'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> unstable_useForkRef <span class="token keyword">as</span> useForkRef <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@mui/utils'</span><span class="token punctuation">;</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span>
    getRootProps<span class="token punctuation">,</span>
    getInputProps<span class="token punctuation">,</span>
    getListboxProps<span class="token punctuation">,</span>
    getOptionProps<span class="token punctuation">,</span>
    popupOpen<span class="token punctuation">,</span>
    anchorEl<span class="token punctuation">,</span>
    setAnchorEl<span class="token punctuation">,</span>
    groupedOptions<span class="token punctuation">,</span>
  <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useAutocomplete</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> rootRef <span class="token operator">=</span> <span class="token function">useForkRef</span><span class="token punctuation">(</span>ref<span class="token punctuation">,</span> setAnchorEl<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token punctuation">(</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span></span><span class="token punctuation">></span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator">...</span><span class="token function">getRootProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span> <span class="token attr-name">ref</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>rootRef<span class="token punctuation">}</span></span><span class="token punctuation">></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator">...</span><span class="token function">getInputProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
      <span class="token punctuation">{</span>anchorEl <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Popper</span></span> <span class="token attr-name">open</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>popupOpen<span class="token punctuation">}</span></span> <span class="token attr-name">anchorEl</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>anchorEl<span class="token punctuation">}</span></span><span class="token punctuation">></span></span>
          <span class="token punctuation">{</span>groupedOptions<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator">...</span><span class="token function">getListboxProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span>
              <span class="token punctuation">{</span>groupedOptions<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">option<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span> <span class="token spread"><span class="token punctuation">{</span><span class="token operator">...</span><span class="token function">getOptionProps</span><span class="token punctuation">(</span><span class="token punctuation">{</span> option<span class="token punctuation">,</span> index <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span>option<span class="token punctuation">.</span>label<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
              <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">}</span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span>
          <span class="token punctuation">)</span><span class="token punctuation">}</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Popper</span></span><span class="token punctuation">></span></span>
      <span class="token punctuation">)</span><span class="token punctuation">}</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span></span><span class="token punctuation">></span></span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

Here's a complete demo that renders the listbox inside a Popper: