1. What renders?
Beginnerjsxfunction Greeting() {
const name = 'Sam'
return <h1>Hello, {name}!</h1>
}
Answer: Hello, Sam!
Curly braces embed a JavaScript expression in JSX, so `{name}` is evaluated rather than printed literally. Anything that produces a value works there — a variable, a function call, a ternary — but statements like `if` do not.
Official documentation →2. This counter always displays 1 no matter how long it runs. Which line is the cause?
Advancedjsx1 function Timer() {
2 const [count, setCount] = useState(0)
3 useEffect(() => {
4 const id = setInterval(() => setCount(count + 1), 1000)
5 return () => clearInterval(id)
6 }, [])
7 return <p>{count}</p>
8 }
Answer: Line 4 — the interval closes over the initial count, which never updates
With an empty dependency array the effect runs once, and the interval callback captures `count` as 0 forever — so it sets 0 + 1 on every tick. The fix is the updater form, `setCount(c => c + 1)`, which reads the latest value instead of the captured one. This is the classic stale closure.
Official documentation →3. What renders after the button is clicked once?
Intermediatejsxfunction App() {
const [items, setItems] = useState(['a'])
const add = () => {
items.push('b')
setItems(items)
}
return <button onClick={add}>{items.length}</button>
}
Answer: 1 — the screen does not update
The array is mutated in place, so `setItems` receives the reference React already holds. React compares with Object.is, sees no change and skips the re-render. Always create a new array: `setItems([...items, 'b'])`.
Official documentation →4. This fails to compile. Which line is wrong?
Beginnerjsx1 function Card() {
2 return (
3 <h2>Title</h2>
4 <p>Body</p>
5 )
6 }
Answer: Lines 3-4 — a component must return a single root element
JSX compiles to a single expression, so sibling elements need a wrapper. Use a `<div>`, or a Fragment (`<>...</>`) when you do not want an extra DOM node — inside a table or a flex container an extra div would break the layout.
Official documentation →5. This fetches on every single render, hammering the API. Which line is wrong?
Intermediatejsx1 function User({ id }) {
2 const [user, setUser] = useState(null)
3 useEffect(() => {
4 fetch(`/api/user/${id}`).then(r => r.json()).then(setUser)
5 })
6 return <p>{user?.name}</p>
7 }
Answer: Line 5 — the dependency array is missing entirely
With no second argument the effect runs after every commit, and because it sets state that schedules another render — an infinite loop. Adding `[id]` runs it only when the id changes. Note that omitting the array is quite different from passing `[]`.
Official documentation →6. The button is clicked once. What is logged?
Advancedjsxfunction App() {
const [n, setN] = useState(0)
const onClick = () => {
setN(n + 1)
setN(n + 1)
console.log(n)
}
return <button onClick={onClick}>{n}</button>
}
Answer: 0 is logged, and n becomes 1
State variables are constants within a render, so `n` is 0 throughout the handler and both calls set it to 1. The log also sees 0 — setting state does not change the current render's variable. Using `setN(x => x + 1)` twice would produce 2.
Official documentation →7. What renders when items is an empty array?
Intermediatejsxreturn <div>{items.length && <List items={items} />}</div>
Answer: A literal 0 on the page
`&&` returns its left operand when falsy, and JSX renders the number 0 as text — unlike false, null and undefined, which render nothing. Use `items.length > 0 && ...` or a ternary. It is one of the most common visual bugs in React.
Official documentation →8. In React 18, how many times does this component re-render when the button is clicked once?
Advancedjsxfunction App() {
const [a, setA] = useState(0)
const [b, setB] = useState(0)
console.log('render')
return <button onClick={() => { setA(1); setB(1) }}>go</button>
}
Answer: Once — the updates are batched
React batches state updates that happen in the same event, so both are applied in one re-render. React 18 extended this automatic batching to promises, timeouts and native handlers too — in React 17 an update inside a `setTimeout` would have rendered twice.
Official documentation →9. What does the child render?
Beginnerjsxfunction App() {
return <Hello name="Ali" age={30} />
}
function Hello({ name, age }) {
return <p>{name} is {age}</p>
}
Answer: Ali is 30
Props pass data from parent to child. Strings use quotes; anything else — numbers, booleans, arrays, functions — goes in braces. Destructuring in the parameter list is the usual way to read them.
Official documentation →10. Fill in the blank to add state to this component.
Beginnerjsxconst [count, setCount] = ____(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
Answer: useState
`useState` returns the current value and a setter. The argument is the initial value, used only on the first render. Changing state through the setter is what tells React to re-render — assigning to `count` directly would do nothing.
Official documentation →11. The button is clicked once. What is the final value of n?
Intermediatejsxconst [n, setN] = useState(0)
const onClick = () => {
setN(n + 1)
setN(n + 1)
setN(n + 1)
}
Answer: 1
`n` is a constant within this render, so all three calls compute 0 + 1 and set the same value. The updater form reads the pending value instead — `setN(x => x + 1)` three times would give 3.
Official documentation →12. This effect fires on every render even though the id rarely changes. Which line is responsible?
Advancedjsx1 function Profile({ userId }) {
2 const options = { include: ['posts'] }
3 useEffect(() => {
4 fetchUser(userId, options)
5 }, [userId, options])
6 return null
7 }
Answer: Line 2 — a new object is created each render, so the dependency is never equal
Dependencies are compared with Object.is, and an object literal is a fresh reference on every render, so the check always fails. Either move the constant outside the component, wrap it in `useMemo`, or depend on the primitive values inside it.
Official documentation →13. What happens when the button is clicked?
Beginnerjsxfunction App() {
let count = 0
return <button onClick={() => { count++ }}>{count}</button>
}
Answer: The number stays 0 on screen
A plain variable is recreated on every render and changing it does not tell React to re-render, so the screen never updates. State exists precisely for values that should survive renders and trigger one when they change.
Official documentation →14. Fill in the blank so the input is a controlled component.
Intermediatejsxconst [name, setName] = useState('')
return <input value={name} ____={e => setName(e.target.value)} />
Answer: onChange
React's `onChange` fires on every keystroke — unlike the native DOM change event, which only fires on blur. Supplying `value` without `onChange` makes the field read-only, and React warns about exactly that in development.
Official documentation →15. Items are re-ordered. What happens to the input's typed text?
Advancedjsx{items.map((item, i) => (
<li key={i}>
<input defaultValue={item.name} />
</li>
))}
Answer: Text stays with the position, so it appears attached to the wrong item
Using the array index as a key tells React that position identifies the element, so when the order changes React reuses the DOM node at each position and only swaps the props. Uncontrolled input state stays put while the labels move. Use a stable id from the data instead.
Official documentation →16. What is logged when this component mounts?
Intermediatejsxfunction App() {
console.log('render')
useEffect(() => console.log('effect'), [])
return null
}
Answer: 'render' then 'effect'
The component body runs first to produce the element tree; effects run after React has committed to the DOM and the browser has painted. That is why an effect can safely read layout — the DOM already exists by then.
Official documentation →17. This calls handleClick immediately on render instead of on click. Which line is wrong?
Beginnerjsx1 function App() {
2 return (
3 <button onClick={handleClick()}>
4 Delete
5 </button>
6 )
7 }
Answer: Line 3 — the function is invoked; pass a reference or a wrapper instead
`handleClick()` calls the function during render and hands its return value to onClick. Pass `handleClick` bare, or wrap it as `() => handleClick(id)` when you need arguments. If the handler sets state, this produces an infinite render loop.
Official documentation →18. Deleting an item from the middle of this list leaves the wrong checkbox ticked. Which line is the cause?
Intermediatejsx1 {todos.map((todo, i) => (
2 <li key={i}>
3 <input type="checkbox" defaultChecked={todo.done} />
4 {todo.text}
5 </li>
6 ))}
Answer: Line 2 — the index as key ties DOM state to position, not to the item
When an item is removed, every later item shifts down an index. React matches by key, so it reuses the DOM node at each position and just swaps the label — the checkbox state stays put. Use a stable `todo.id` as the key.
Official documentation →19. What renders when isLoggedIn is false?
Beginnerjsxreturn <div>{isLoggedIn ? <Dashboard /> : <Login />}</div>
Answer: The Login component
A ternary is the usual way to choose between two elements in JSX, since `if` statements are not expressions and cannot go inside braces. For a single optional element, `{condition && <X />}` is shorter — but be careful when the condition is a number.
Official documentation →20. What does the child receive?
Intermediatejsxfunction Parent() {
return <Child count={0} label="" active={false} />
}
function Child({ count, label, active }) {
return <p>{count} {label || 'none'} {String(active)}</p>
}
Answer: 0 none false
All three props arrive with their real values — 0, an empty string and false are valid props, not missing ones. The `label || 'none'` fallback fires because an empty string is falsy, which is the same trap that `??` avoids.
Official documentation →21. What does this render?
Beginnerjsxconst items = ['a', 'b']
return <ul>{items.map(i => <li key={i}>{i}</li>)}</ul>
Answer: Two list items: a and b
React renders an array of elements as siblings. Each needs a `key` that is stable and unique among them, so React can match elements across renders — omitting it produces a console warning, and using the array index causes state to stick to positions rather than items.
Official documentation →22. What does this render after the button is clicked?
Advancedjsxfunction App() {
const ref = useRef(0)
const [, force] = useState(0)
return (
<button onClick={() => { ref.current++ }}>
{ref.current}
</button>
)
}
Answer: 0 — mutating a ref does not trigger a re-render
A ref is a mutable box that persists across renders but is deliberately outside React's update cycle — changing `.current` schedules nothing. That is exactly why refs suit values you need to remember but not display, such as a timer id or a previous value.
Official documentation →23. Which of these correctly update a single field in an object held in state? Select all that apply.
Intermediatejsxconst [form, setForm] = useState({ name: '', email: '' })
Answer: setForm({ ...form, name: 'Sam' })
Spreading into a new object, the updater form, and `Object.assign` onto a fresh target all produce a new reference React will notice. Mutating in place does not — React sees the same object and skips the render. The updater form is safest when several updates may batch together.
Official documentation →24. Every consumer of this context re-renders on any parent render, even when the value has not changed. Which line explains it?
Advancedjsx1 function Provider({ children }) {
2 const [user, setUser] = useState(null)
3 return (
4 <Ctx.Provider value={{ user, setUser }}>
5 {children}
6 </Ctx.Provider>
7 )
8 }
Answer: Line 4 — the object literal is a new reference each render
Context consumers re-render whenever the provider's `value` changes by identity, and a fresh object literal changes every time. Wrap it in `useMemo` keyed on `[user]`. Splitting rarely-changing state into a separate context is the other common remedy.
Official documentation →