React Interview Typing Practice
Core hooks, patterns, and code snippets every React developer should be able to type fluently. Ideal for interview prep and building muscle memory.
Core Hooks Reference
These ten hooks cover the vast majority of React use cases. Know them cold before any interview.
| Hook | Purpose |
|---|---|
useState | Declare reactive state in a function component |
useEffect | Run side effects after render; cleanup with returned function |
useRef | Mutable container that doesn't trigger re-renders |
useMemo | Memoize an expensive computation |
useCallback | Memoize a function to prevent unnecessary re-creation |
useContext | Consume a React context without prop drilling |
useReducer | Manage complex state with action-based updates |
useLayoutEffect | Fires synchronously after DOM mutations — before paint |
useId | Generate unique IDs stable across server and client |
useImperativeHandle | Expose imperative methods via a ref to a parent |
Common Patterns — Code Snippets
These are the patterns that come up repeatedly in interviews and day-to-day React work. Type them until they feel automatic.
Conditional Rendering
function Alert({ show, message }) {
if (!show) return null;
return <div className="alert">{message}</div>;
}
// Inline with &&
{isLoggedIn && <UserMenu />}
// Ternary
{isPro ? <ProDashboard /> : <FreeDashboard />}List Rendering
function LanguageList({ languages }) {
return (
<ul>
{languages.map((lang) => (
<li key={lang.id}>{lang.name}</li>
))}
</ul>
);
}useState — Counter
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}useEffect — Data Fetching
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
async function fetchUser() {
const res = await fetch(`/api/users/${userId}`);
const data = await res.json();
if (!cancelled) {
setUser(data);
setLoading(false);
}
}
fetchUser();
return () => { cancelled = true; };
}, [userId]);
if (loading) return <p>Loading...</p>;
return <div>{user?.name}</div>;
}Controlled Form Input
import { useState } from 'react';
function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
function handleSubmit(e) {
e.preventDefault();
console.log({ email, password });
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit">Log in</button>
</form>
);
}Custom Hook
import { useState, useEffect } from 'react';
function useLocalStorage(key, defaultValue) {
const [value, setValue] = useState(() => {
try {
const stored = localStorage.getItem(key);
return stored !== null ? JSON.parse(stored) : defaultValue;
} catch {
return defaultValue;
}
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}React Interview Tips
- → Always explain the dependency array when discussing useEffect
- → Know when useMemo and useCallback actually help vs. hurt (overhead is real)
- → useState updater functions (functional form) prevent stale closure bugs
- → Custom hooks are just functions that call other hooks — name them use*
- → key prop in lists must be stable and unique — avoid array index when list can reorder
- → Controlled vs uncontrolled inputs: controlled = React owns state, uncontrolled = DOM owns it
Practice typing these in CodeSpeedTest →
Typing React snippets from memory is a different skill than reading them. Start with Hello World and progress to hooks-heavy examples.