React Hooks useEffect Hook 2 — Questions and Answers
Question 1: What hook should you use instead of useEffect when you need the effect to run synchronously before the browser paints?
- useMemo
- useLayoutEffect (Correct answer)
- useCallback
- useRef
Correct answer: useLayoutEffect
useLayoutEffect fires synchronously after DOM mutations but before the browser paints, similar to componentDidMount.
Question 2: How do you fetch data on component mount using useEffect?
- useEffect(fetchData)
- useEffect(fetchData, [])
- useEffect(() => { fetchData(); }, []) (Correct answer)
- useEffect(async () => fetchData(), [])
Correct answer: useEffect(() => { fetchData(); }, [])
You call the async function inside a non-async effect callback with an empty dependency array to fetch on mount.
Question 3: Why can't you directly make the useEffect callback an async function?
- React does not support async syntax
- Async functions return a Promise, but useEffect expects a cleanup function or nothing (Correct answer)
- Async effects don't work in strict mode
- It would cause infinite loops
Correct answer: Async functions return a Promise, but useEffect expects a cleanup function or nothing
useEffect expects the callback to return either undefined or a cleanup function, not a Promise.
Question 4: Which dependency array value causes useEffect to run on every render?
- []
- [undefined]
- No array at all (omit the second argument) (Correct answer)
- [null]
Correct answer: No array at all (omit the second argument)
Omitting the dependency array entirely tells React the effect has no condition and should run after every render.
Question 5: What is a common mistake when including objects or arrays in useEffect dependencies?
- React ignores non-primitive dependencies
- A new reference is created on each render, causing infinite re-runs (Correct answer)
- Objects must be stringified first
- Arrays cannot be dependencies
Correct answer: A new reference is created on each render, causing infinite re-runs
Objects and arrays are compared by reference; a new literal on each render will always trigger the effect.
Question 6: How do you cancel a fetch request inside a useEffect cleanup?
- Call fetch.cancel()
- Use an AbortController and call abort() in the cleanup function (Correct answer)
- Set a flag and check it after await
- Use Promise.reject() in the cleanup
Correct answer: Use an AbortController and call abort() in the cleanup function
AbortController.abort() signals the fetch to stop, and checking the signal prevents state updates after unmount.
What hook should you use instead of useEffect when you need the effect to run synchronously before the browser paints?