React Best Practices

Learn hooks, state management, and modern patterns. Build components that scale.

0/12
Challenges Completed
0%
Progress
0
Your Total Score
1. The Infinite Re-render
Intermediate
A common React pitfall is causing infinite loops by creating new object references in the render body and passing them as dependencies to `useEffect`. ### Your Task: - Fix the `UserProfile` component that is currently crashing the browser (simulated) - The `fetchUser` function is being recreated on every render - When passed to `useEffect`, it triggers another render, creating a loop - Use `useCallback` or move the function inside the effect to fix it
2. The Memory Leak
Intermediate
Intervals and subscriptions must be cleaned up! If you don't return a cleanup function from `useEffect`, multiple intervals will pile up, causing performance issues and erratic behavior. ### Your Task: - Fix the `Timer` component where the count speeds up every time you re-render - The effect sets an interval but never clears it - Return a cleanup function that calls `clearInterval`
3. Race Conditions
Advanced
When fetching data asynchronously, requests can return out of order. If the user clicks 'Next' then 'Previous' quickly, the 'Next' request might finish *after* 'Previous', showing the wrong data. ### Your Task: - Implement a 'stale' or 'cancelled' flag in the `useEffect` - Create a boolean variable `ignore` set to false - In the cleanup function, set `ignore` to true - Only update state if `!ignore`
4. Stale Closures
Advanced
Closures in JavaScript capture variables at the time they are created. In React, this means `setTimeout` or event listeners might see 'old' state values if you're not careful. ### Your Task: - Fix the `DelayedLogger` component - The user clicks 'Start Log' (count is 0), then clicks 'Increment' 5 times (count is 5) - But when the log fires, it prints 'Count: 0'! - Update the code to ensure it sees the *current* count, possibly using `useRef`
5. Expensive Calculations
Advanced
Not everything needs to be memoized, but expensive calculations that run on every render definitely do. ### Your Task: - Optimize the `PrimeFinder` component - Finding the 1000th prime number is slow - Currently, typing in the input field causes lag because `findNthPrime` runs on every keystroke - Wrap the calculation in `useMemo` so it only runs when `n` changes
6. Unnecessary Re-renders
Advanced
Passing new function references to optimized children breaks optimizations. `React.memo` only works if props remain stable. ### Your Task: - The `ExpensiveChart` component is wrapped in `React.memo`, but it still re-renders whenever the parent updates - This is because `handleResize` is a new function every time - Wrap `handleResize` in `useCallback` to stabilize its reference
7. Derived State Anti-Pattern
Advanced
A common mistake is syncing state with `useEffect`. If a value can be calculated from existing props or state, compute it during render! Don't put it in state. ### Your Task: - Refactor `FullName` to remove the `fullName` state and the `useEffect` - Calculate `fullName` directly in the component body - This removes an unnecessary render pass and simplifies the code
8. Custom Hook: useDebounce
Advanced
Debouncing is crucial for search inputs to avoid spamming your API. Let's encapsulate this logic in a reusable hook. ### Your Task: - Implement `useDebounce(value, delay)` - It should return a `debouncedValue` that only updates after the delay has passed without changes - Use `useEffect` with a timeout and cleanup - This allows the UI to update instantly (input value) while the API call waits (debounced value)
9. Context Optimization
Advanced
Context providers that pass unstable objects cause ALL consumers to re-render, even if the data they need hasn't changed. This is a potential performance killer. ### Your Task: - The `ThemeProvider` creates a new `{ theme, toggleTheme }` object every render - Wrap this value in `useMemo` so it stays referentially stable - This ensures that `Header`, which consumes context, only re-renders when the thread actually changes
10. Layout Shift Fix
Advanced
`useEffect` runs *after* the browser paints. If you manipulate the DOM (like positioning a tooltip) inside it, the user might see a flicker or jump. `useLayoutEffect` runs *before* paint. ### Your Task: - Fix the `Tooltip` component where the tooltip flickers briefly at (0,0) before jumping to the correct position - Change `useEffect` to `useLayoutEffect` to block painting until the position is calculated
11. Compound Components
Advanced
Compound components allow you to create expressive APIs like `<Toggle><Toggle.On>...</Toggle.On></Toggle>` where parent and children share state implicitly. ### Your Task: - Create a `Toggle` component that uses `createContext` to share `isOn` and `toggle` state - Create `Toggle.On` that only renders children if `isOn` is true - Create `Toggle.Off` that only renders children if `isOn` is false - Create `Toggle.Button` that triggers the toggle
12. Optimistic UI
Advanced
Users expect instant feedback. Optimistic UI updates the interface *immediately* while the server request processes, reverting only if it fails. ### Your Task: - Implement an optimistic 'Like' button - When clicked, immediately increment the `likes` count locally - Then call `api.likePost()` - If `api.likePost()` throws an error, revert the count back to its original value

Ready to Learn React?

Start with the basics and work your way up to advanced patterns!

Start First Challenge