Controlled Input with Suggestion List
Build the foundation: a controlled input that shows a filtered suggestion dropdown below it.
Controlled Input with Suggestion List is a free React Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Component Structure Overview
An autocomplete component has two main parts: a controlled text input and a dropdown suggestion list. The input sits in normal document flow, and the dropdown is positioned absolutely directly below it. Together they function as a single interactive widget, though they are separate DOM elements.
Required State Variables
You need four state variables: inputValue (string — what is typed), suggestions (array — current matching items), isOpen (boolean — whether the dropdown is visible), and selectedIndex (number — which suggestion is highlighted for keyboard navigation, starts at -1 for none selected).
Controlling the Input
Make the input fully controlled: value={inputValue} and onChange={e => setInputValue(e.target.value)}. This gives React full control over the displayed text. Every keystroke updates state, which triggers a re-render with the new value. Never use an uncontrolled input for autocomplete — you need to read and set the value programmatically.
Filtering from a Static List
When suggestions come from a local array, filter on every render based on inputValue: compare each item using item.toLowerCase().includes(inputValue.toLowerCase()). You can compute this with useMemo if the list is large to avoid recomputing on every re-render. For small lists, inline filtering is fine.
Showing and Hiding the Dropdown
Open the dropdown when inputValue.length > 0 and suggestions.length > 0. Close it when the input is blurred (with a small delay to allow suggestion clicks to register first), when a suggestion is selected, or when the Escape key is pressed. Set isOpen accordingly to drive the conditional rendering.
Handling Blur with a Delay
The onBlur event fires when the input loses focus, which happens when the user clicks a suggestion. If you close the dropdown immediately on blur, the click on the suggestion never registers because the dropdown disappears before the click fires. Use setTimeout(() => setIsOpen(false), 150) to give the click time to register.
Styling the Dropdown
Position the dropdown with position: absolute so it overlays content below the input rather than pushing it down. Set a high z-index (100+) so it appears above other content. Set a max-height with overflow-y: auto to prevent the list from growing too tall when many results exist.
Making Suggestions Clickable
Each suggestion item should have an onClick handler: onClick={() => { setInputValue(suggestion); setIsOpen(false); }}. This sets the input to the selected suggestion and closes the dropdown. The selection feels instant and natural, matching the behavior users expect from autocomplete fields.
Preventing Blur Before Click
An alternative to the blur timeout is to use onMouseDown={e => e.preventDefault()} on each suggestion item. This prevents the mousedown from stealing focus from the input, so the blur event never fires when clicking a suggestion. The input retains focus and the click handler fires cleanly.
Keyboard Interaction Overview
Good autocomplete must be keyboard-navigable. The user should be able to press ArrowDown to highlight the first suggestion, continue pressing to move down the list, press Enter to select, and press Escape to close without selecting. This is implemented by handling onKeyDown on the input element.
Resetting selectedIndex on Input Change
Whenever the user types and inputValue changes, reset selectedIndex to -1. This clears any previous keyboard selection so the new set of filtered suggestions starts with nothing highlighted. A stale selection index pointing to a different item after the list changes is confusing and incorrect.
Blur vs MouseDown Event Order
Why use onMouseDown with e.preventDefault() on suggestion items instead of relying on a blur timeout?
Lesson Recap: Controlled Input with Suggestions
An autocomplete widget needs four state variables: inputValue, suggestions, isOpen, and selectedIndex. Use a controlled input, filter suggestions based on input, and manage dropdown visibility via isOpen. Handle the blur-before-click race condition with either a timeout or onMouseDown preventDefault. Reset selectedIndex whenever the input changes.
Frequently asked questions
Is the “Controlled Input with Suggestion List” lesson free?
Yes — the full text of “Controlled Input with Suggestion List” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “Controlled Input with Suggestion List”?
Build the foundation: a controlled input that shows a filtered suggestion dropdown below it. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Controlled Input with Suggestion List” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Controlled Input with Suggestion List
- Keyboard Navigation in Suggestion Lists
- Async Suggestions with Debounce
- Accessibility for Autocomplete Widgets