Coding exercise: build an autocomplete dropdown in React.
Model answer
Combine a debounced input with a list of matches, keyboard control (arrows and Enter) and the right ARIA roles. Keep an "active index" in state.
function Autocomplete({ options, onSelect }) {
const [q, setQ] = useState('');
const [active, setActive] = useState(0);
const matches = q ? options.filter((o) => o.toLowerCase().includes(q.toLowerCase())).slice(0, 6) : [];
const choose = (v) => { onSelect(v); setQ(v); setActive(0); };
const onKey = (e) => {
if (e.key === 'ArrowDown') { e.preventDefault(); setActive((a) => Math.min(a + 1, matches.length - 1)); }
if (e.key === 'ArrowUp') { e.preventDefault(); setActive((a) => Math.max(a - 1, 0)); }
if (e.key === 'Enter' && matches[active]) choose(matches[active]);
};
return (
<div>
<input role="combobox" aria-expanded={matches.length > 0} aria-controls="opts" value={q}
onChange={(e) => { setQ(e.target.value); setActive(0); }} onKeyDown={onKey} />
{matches.length > 0 && (
<ul id="opts" role="listbox">{matches.map((m, i) => (
<li key={m} role="option" aria-selected={i === active} onMouseDown={() => choose(m)}>{m}</li>))}</ul>)}
</div>
);
}onMouseDown is used so the choice happens before the input loses focus. For remote data, debounce the query and cancel old requests.
Tips
- Mention highlighting the matched text and closing the list on Escape.
Practise it yourself in the React and Angular code playground.
Learn this topic
React.js Full Course: Beginner to Advanced .
Sign in to add your own answer.
More questions
- Coding exercise: build a Todo application in React.
- Coding exercise: create a search box with debounce in React.
- Coding exercise: fetch API data and display it in a table in React.
- Coding exercise: implement pagination in React.
- Coding exercise: create a login form with validation in React.
- Coding exercise: build a parent-child communication example in React.