Bird
Raised Fist0
Reactframework~20 mins

useCallback hook in React - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
useCallback Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ component_behavior
intermediate
2:00remaining
What is the output of this React component using useCallback?

Consider this React component that uses useCallback. What will be logged when the button is clicked twice?

React
import React, { useState, useCallback } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const increment = useCallback(() => {
    console.log('Count before increment:', count);
    setCount(count + 1);
  }, []);

  return (
    <button onClick={increment}>Increment</button>
  );
}

export default Counter;
ALogs 'Count before increment: 0' both times the button is clicked.
BLogs 'Count before increment: 0' first click, then 'Count before increment: 1' second click.
CLogs 'Count before increment: 1' both times the button is clicked.
DLogs 'Count before increment: 0' first click, then 'Count before increment: 2' second click.
Attempts:
2 left
💡 Hint

Remember that useCallback with an empty dependency array keeps the same function instance and closes over the initial count value.

❓ state_output
intermediate
2:00remaining
What is the value of count after clicking the button twice?

Given this React component, what will be the value of count after clicking the button two times?

React
import React, { useState, useCallback } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const increment = useCallback(() => {
    setCount(prev => prev + 1);
  }, []);

  return (
    <button onClick={increment}>Increment</button>
  );
}

export default Counter;
Acount will be 1
Bcount will be 2
Ccount will be 0
Dcount will be undefined
Attempts:
2 left
💡 Hint

Look at how setCount uses a function to update state.

📝 Syntax
advanced
2:00remaining
Which option correctly uses useCallback to memoize a function depending on a prop?

Which code snippet correctly memoizes handleClick so it updates when propValue changes?

Aconst handleClick = useCallback(() => { console.log(propValue); }, []);
Bconst handleClick = useCallback(() => { console.log(propValue); }, [setPropValue]);
Cconst handleClick = useCallback(() => { console.log(propValue); });
Dconst handleClick = useCallback(() => { console.log(propValue); }, [propValue]);
Attempts:
2 left
💡 Hint

Think about which dependencies should be included to update the callback when props change.

🔧 Debug
advanced
2:00remaining
Why does this useCallback hook cause a stale closure bug?

Examine this code. Why does the handleClick function always log the initial value of count?

React
import React, { useState, useCallback } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log(count);
  }, []);

  return (
    <>
      <button onClick={() => setCount(count + 1)}>Increase</button>
      <button onClick={handleClick}>Log Count</button>
    </>
  );
}

export default Counter;
ABecause count is updated asynchronously, the console.log always shows the previous value.
BBecause setCount is not included in dependencies, the function does not update.
CBecause useCallback has an empty dependency array, it captures the initial count value and never updates.
DBecause handleClick is not called inside useEffect, it does not update.
Attempts:
2 left
💡 Hint

Think about how dependency arrays affect closures in hooks.

🧠 Conceptual
expert
2:00remaining
Which statement best describes the purpose of useCallback in React?

Choose the best explanation for why and when to use useCallback in React components.

A<p>useCallback memoizes a function so it keeps the same reference between renders unless dependencies change, helping to avoid unnecessary re-renders in child components.</p>
B<p>useCallback automatically batches multiple state updates into one render to improve performance.</p>
C<p>useCallback forces React to re-render a component whenever a function changes.</p>
D<p>useCallback replaces useEffect to run side effects only when dependencies change.</p>
Attempts:
2 left
💡 Hint

Think about how React compares props and why function identity matters.

Practice

(1/5)
1. What is the main purpose of the useCallback hook in React?
easy
A. To memoize a function so it doesn't get recreated on every render unless dependencies change
B. To store a value that persists between renders
C. To fetch data from an API asynchronously
D. To create a new state variable

Solution

  1. Step 1: Understand what useCallback does

    useCallback returns a memoized version of a function that only changes if its dependencies change.
  2. Step 2: Compare options with this behavior

    Only To memoize a function so it doesn't get recreated on every render unless dependencies change describes memoizing a function to avoid recreating it unnecessarily.
  3. Final Answer:

    To memoize a function so it doesn't get recreated on every render unless dependencies change -> Option A
  4. Quick Check:

    useCallback = memoize function [OK]
Hint: Remember: useCallback memoizes functions to keep them stable [OK]
Common Mistakes:
  • Confusing useCallback with useState
  • Thinking useCallback stores values instead of functions
  • Assuming useCallback fetches data
2. Which of the following is the correct syntax to use useCallback in a React functional component?
easy
A. const memoizedFn = useCallback(doSomething(), [dependency]);
B. const memoizedFn = useCallback(() => { doSomething(); });
C. const memoizedFn = useCallback(() => { doSomething(); }, [dependency]);
D. const memoizedFn = useCallback(doSomething, dependency);

Solution

  1. Step 1: Recall the correct useCallback signature

    The hook takes a function and an array of dependencies: useCallback(fn, [deps]).
  2. Step 2: Analyze each option

    const memoizedFn = useCallback(() => { doSomething(); }, [dependency]); correctly passes an inline function and dependencies array. const memoizedFn = useCallback(() => { doSomething(); }); misses dependencies array. const memoizedFn = useCallback(doSomething(), [dependency]); calls doSomething() immediately, passing its return value instead of the function. const memoizedFn = useCallback(doSomething, dependency); passes dependency without array brackets, invalid.
  3. Final Answer:

    const memoizedFn = useCallback(() => { doSomething(); }, [dependency]); -> Option C
  4. Quick Check:

    useCallback(fn, [deps]) [OK]
Hint: useCallback needs a function and an array of dependencies [OK]
Common Mistakes:
  • Omitting the dependencies array
  • Passing dependencies without array brackets
  • Passing function call instead of function reference
3. Consider this React component code:
const MyComponent = () => {
  const [count, setCount] = React.useState(0);
  const increment = React.useCallback(() => {
    setCount(count + 1);
  }, [count]);
  return <button onClick={increment}>Increment</button>;
};

What happens when the button is clicked multiple times quickly?
medium
A. The count increments correctly each time
B. The code throws an error because of missing dependencies
C. The count increments only once and then stops
D. The count increments but may lag behind due to stale closure

Solution

  1. Step 1: Understand the closure inside useCallback

    The increment function uses count from its dependencies. Because count is in the dependency array, the function updates when count changes, but rapid clicks may use a stale value.
  2. Step 2: Analyze behavior on quick clicks

    Rapid clicks may cause the function to use an outdated count value due to closure, causing increments to lag behind actual clicks.
  3. Final Answer:

    The count increments but may lag behind due to stale closure -> Option D
  4. Quick Check:

    useCallback with state dependency can cause stale closures [OK]
Hint: State in useCallback can be stale if updated rapidly [OK]
Common Mistakes:
  • Assuming count always updates instantly
  • Ignoring closure behavior in hooks
  • Thinking useCallback prevents all stale data issues
4. Identify the bug in this code using useCallback:
const MyComponent = () => {
  const [value, setValue] = React.useState(0);
  const handleClick = React.useCallback(() => {
    setValue(value + 1);
  }, []);
  return <button onClick={handleClick}>Click</button>;
};
medium
A. Missing dependency value in the dependency array causes stale state updates
B. Using useCallback without dependencies causes infinite re-renders
C. setValue should not be called inside useCallback
D. The function should not be memoized with useCallback

Solution

  1. Step 1: Check the dependency array of useCallback

    The callback uses value but the dependency array is empty, so the function never updates with new value.
  2. Step 2: Understand the effect of missing dependencies

    Because value is missing, the callback uses the initial value forever, causing stale increments.
  3. Final Answer:

    Missing dependency value in the dependency array causes stale state updates -> Option A
  4. Quick Check:

    Dependencies must include all used variables [OK]
Hint: Always include all variables used inside useCallback in dependencies [OK]
Common Mistakes:
  • Leaving dependency array empty when variables are used
  • Thinking setState functions need dependencies
  • Confusing useCallback with useMemo
5. You want to optimize a child component that receives a callback prop to avoid unnecessary re-renders. Which approach correctly uses useCallback to achieve this?
const Parent = () => {
  const [count, setCount] = React.useState(0);

  // Which is correct?
  const handleClick = ???

  return <Child onClick={handleClick} />;
};
hard
A. const handleClick = React.useCallback(() => setCount(count + 1), [count]);
B. const handleClick = React.useCallback(() => setCount(c => c + 1), []);
C. const handleClick = () => setCount(count + 1);
D. const handleClick = React.useCallback(() => setCount(count + 1));

Solution

  1. Step 1: Understand the goal to avoid unnecessary re-renders

    We want handleClick to be stable and not change unless needed, so the child doesn't re-render unnecessarily.
  2. Step 2: Analyze each option's dependency array and function

    const handleClick = React.useCallback(() => setCount(count + 1), [count]); depends on count, so it changes every time count changes, causing re-renders. const handleClick = React.useCallback(() => setCount(c => c + 1), []); uses functional update c => c + 1 and empty dependencies, so handleClick is stable. const handleClick = () => setCount(count + 1); recreates function every render. const handleClick = React.useCallback(() => setCount(count + 1)); misses dependencies array, which is invalid.
  3. Final Answer:

    const handleClick = React.useCallback(() => setCount(c => c + 1), []); -> Option B
  4. Quick Check:

    Stable callback with functional update and empty deps = const handleClick = React.useCallback(() => setCount(c => c + 1), []); [OK]
Hint: Use functional updates with empty deps to keep callback stable [OK]
Common Mistakes:
  • Including state in dependencies causing new functions each render
  • Not using functional updates when deps are empty
  • Omitting dependency array causing bugs
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard