Skip to main content

Autocomplete (Online API)

Difficulty: Advanced

Problem Statement​

Fetch remote suggestions (GitHub users) based on debounced search input.

Live Demo​

Try the running app below β€” this is the target behavior for the challenge.

Autocomplete (Online API) β€” Live Demo

    What Interviewers Expect​

    • Debounce API calls.
    • Loading and error states.
    • Ignore/cancel stale responses.

    Step-by-Step Implementation​

    Step 1 β€” Debounced fetch​

    Delay network call until user pauses typing.

    timer.current = setTimeout(() => search(q), 400);

    Step 2 β€” Fetch + render​

    Call GitHub search API and map results.

    fetch(`https://api.github.com/search/users?q=${q}&per_page=5`)

    Step 3 β€” Cleanup​

    Clear timeout on unmount to avoid leaks.

    useEffect(() => () => clearTimeout(timer.current), []);

    Complete Implementation​

    Copy-paste ready single-file solution. Use this as your reference after attempting the challenge yourself, or paste it into CodeSandbox / StackBlitz to run locally.

    App.jsx
    import React, {useCallback, useEffect, useRef, useState} from 'react';

    export default function App() {
    const [term, setTerm] = useState('');
    const [users, setUsers] = useState([]);
    const [loading, setLoading] = useState(false);
    const timer = useRef(null);

    const search = useCallback((query) => {
    if (!query.trim()) {
    setUsers([]);
    return;
    }

    setLoading(true);
    fetch(`https://api.github.com/search/users?q=${encodeURIComponent(query)}&per_page=5`)
    .then((response) => response.json())
    .then((data) => setUsers(data.items || []))
    .catch(() => setUsers([]))
    .finally(() => setLoading(false));
    }, []);

    useEffect(() => () => clearTimeout(timer.current), []);

    const onChange = (event) => {
    const query = event.target.value;
    setTerm(query);
    clearTimeout(timer.current);
    timer.current = setTimeout(() => search(query), 400);
    };

    return (
    <div>
    <input
    value={term}
    onChange={onChange}
    placeholder="Search GitHub users"
    />
    {loading && <p style={{color: '#666'}}>Loading…</p>}
    <ul>
    {users.map((user) => (
    <li key={user.id}>{user.login}</li>
    ))}
    </ul>
    </div>
    );
    }

    Final Checklist​

    • UI works for primary flow
    • Edge cases handled (empty/disabled/loading where relevant)
    • State updates are immutable
    • Components are readable and reasonably split
    • You can explain trade-offs out loud in an interview

    Next Challenge​

    Continue to the next item in the sidebar when you're comfortable implementing this from scratch in 30–45 minutes.