Coding practice
React Coding Questions
20 hands-on challenges with prompts and solution sketches for React interview rounds.
Challenge set
20 coding questions
1. Controlled Input
jsxBuild a controlled text input.
function NameField() {
const [value, setValue] = useState("");
return (
<input value={value} onChange={(e) => setValue(e.target.value)} />
);
} 2. Toggle State
jsxToggle a boolean with a button.
function Toggle() {
const [on, setOn] = useState(false);
return <button onClick={() => setOn((v) => !v)}>{on ? "On" : "Off"}</button>;
} 3. List Rendering
jsxRender a list with stable keys.
function ItemList({ items }) {
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.label}</li>
))}
</ul>
);
} 4. Fetch on Mount
jsxFetch data once on mount with cleanup.
function Users() {
const [users, setUsers] = useState([]);
useEffect(() => {
let active = true;
fetch("/api/users")
.then((r) => r.json())
.then((data) => {
if (active) setUsers(data);
});
return () => {
active = false;
};
}, []);
return <pre>{JSON.stringify(users, null, 2)}</pre>;
} 5. Custom Hook
jsxCreate a useLocalStorage hook.
function useLocalStorage(key, initial) {
const [value, setValue] = useState(() => {
const raw = localStorage.getItem(key);
return raw ? JSON.parse(raw) : initial;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
} 6. Memoized Expensive Calc
jsxMemoize a derived value with useMemo.
function Total({ items }) {
const total = useMemo(
() => items.reduce((sum, item) => sum + item.price, 0),
[items]
);
return <p>Total: {total}</p>;
} 7. Callback Stability
jsxStabilize a callback with useCallback.
function Parent({ onSave }) {
const handleSave = useCallback(() => onSave(), [onSave]);
return <Child onSave={handleSave} />;
} 8. Error Boundary Usage
jsxWrap a subtree with an error boundary component.
function App() {
return (
<ErrorBoundary fallback={<p>Something went wrong.</p>}>
<Dashboard />
</ErrorBoundary>
);
} 9. Conditional Render
jsxRender loading, error, and success states.
function Profile({ status, user, error }) {
if (status === "loading") return <p>Loading...</p>;
if (status === "error") return <p>{error}</p>;
return <h1>{user.name}</h1>;
} 10. Form Submit Handler
jsxPrevent default and read FormData.
function LoginForm({ onSubmit }) {
function handleSubmit(e) {
e.preventDefault();
const data = new FormData(e.currentTarget);
onSubmit(Object.fromEntries(data));
}
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" />
<button type="submit">Login</button>
</form>
);
} 11. Context Provider
jsxCreate a theme context provider.
const ThemeContext = createContext("light");
function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
} 12. Reducer Counter
jsxManage counter state with useReducer.
function reducer(state, action) {
switch (action.type) {
case "inc":
return { count: state.count + 1 };
case "dec":
return { count: state.count - 1 };
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
<p>{state.count}</p>
<button onClick={() => dispatch({ type: "inc" })}>+</button>
</>
);
} 13. Portal Modal
jsxRender a modal into document.body with createPortal.
function Modal({ children }) {
return createPortal(
<div className="modal">{children}</div>,
document.body
);
} 14. Debounced Search
jsxDebounce search input with useEffect.
function Search({ onSearch }) {
const [query, setQuery] = useState("");
useEffect(() => {
const id = setTimeout(() => onSearch(query), 300);
return () => clearTimeout(id);
}, [query, onSearch]);
return <input value={query} onChange={(e) => setQuery(e.target.value)} />;
} 15. Optimistic UI
jsxOptimistically update a liked state.
async function likePost(id, setLiked) {
setLiked(true);
try {
await fetch(`/api/posts/${id}/like`, { method: "POST" });
} catch {
setLiked(false);
}
} 16. Forwarded Ref Input
jsxForward a ref to an input.
const TextInput = forwardRef(function TextInput(props, ref) {
return <input ref={ref} {...props} />;
}); 17. Derived Filtered List
jsxFilter items without extra state.
function FilteredList({ items, query }) {
const filtered = items.filter((item) =>
item.name.toLowerCase().includes(query.toLowerCase())
);
return filtered.map((item) => <div key={item.id}>{item.name}</div>);
} 18. Cleanup Subscription
jsxUnsubscribe on unmount.
useEffect(() => {
const unsubscribe = store.subscribe(setState);
return () => unsubscribe();
}, []); 19. Lazy Route Component
jsxLazy-load a page component.
const Dashboard = lazy(() => import("./Dashboard"));
function App() {
return (
<Suspense fallback={<p>Loading...</p>}>
<Dashboard />
</Suspense>
);
} 20. Key Remount Trick
jsxForce remount by changing key.
function Editor({ draftId }) {
return <RichText key={draftId} />;
}