The components and hooks that come up in React machine coding rounds — debounced search, custom hooks, modals, infinite scroll, autocomplete — with worked solutions.
12 questions4 fresher, 5 mid-level, 3 senior
The machine coding round is usually 30 to 45 minutes to build one small component. Nobody expects a finished product. What is being marked is whether you clarify the requirements before typing, choose sensible state, handle the empty, loading and error cases, and clean up after yourself.
Two habits earn marks in every one of these: say what you are about to do before you do it, and mention the edge case even if you decide not to implement it. Each solution below notes what the interviewer is actually watching for.
1.Build a counter with increment, decrement and reset
Fresher
One piece of state and three handlers. Use the functional updater form, and keep the initial value in a constant so reset has something to return to.
2.Build a search input that debounces its API call
Mid-level
Keep the input controlled for instant feedback, debounce the value with a custom hook, and fire the request from an effect keyed on the debounced value with cancellation in the cleanup.
Hold data, error and status in one state object, fetch in an effect keyed on the URL, abort in the cleanup, and return the triple. Say out loud that in production you would use a query library.
Store the value in a ref and update it in an effect. Because effects run after render, the ref still holds the previous render's value while the component renders.
function usePrevious(value) {
const ref = useRef(undefined);
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current; // the value from the last committed render
}
The whole point is the timing: the render reads ref.current before the effect overwrites it, so it sees the old value. On the first render it is undefined, which callers must handle.
6.Build an accordion where only one section is open at a time
Fresher
Hold the id of the open section in state rather than a boolean per section, so exclusivity is structural. Toggle to null when the open one is clicked again.
Render a radio group styled as stars, track the committed value in state and the hovered value separately, and display the hovered value when there is one. Radios give you keyboard support for free.
Take the current page, total pages and a change handler as props, keep the page in the URL rather than in local state, and render a window of page numbers with ellipses rather than every page.
Put a sentinel element after the list and observe it with IntersectionObserver. When it becomes visible and you are not already loading, fetch the next page. Disconnect the observer in the effect cleanup.
rootMargin starts the fetch before the sentinel is actually visible, so the list rarely appears to stall.
The enabled flag is how you stop firing while a request is in flight or when there are no more pages.
The ref holding the latest callback keeps the observer from being torn down and recreated on every render.
For very long lists, combine it with virtualisation, or the DOM grows without limit.
Likely follow-up questions
Why not use a scroll event listener?
10.Build an accessible modal dialog
Senior
Render it through a portal, close on Escape and on backdrop click, trap focus inside while it is open, and return focus to the element that opened it on close.
Debounce the query, keep the suggestion list and a highlighted index in state, and handle ArrowUp, ArrowDown, Enter and Escape on the input. Wire up the combobox ARIA attributes so the highlighted option is announced.
How would you handle a slow response arriving after a newer one?
12.Implement a useLocalStorage hook
Mid-level
Wrap useState, read the stored value lazily on first render, write on change, and guard every access with try/catch because storage can be unavailable or hold invalid JSON.