Checkpoint: React Fundamentals
This checkpoint is a review milestone that consolidates the React Fundamentals track — JSX, props, fragments, rendering, styling, Strict Mode, effect timing, and immutable state — through a hands-on build challenge and a short quiz. It confirms you can combine these ideas before moving on to deeper hooks.
Learn Checkpoint: React Fundamentals in our free React course — an interactive lesson with runnable examples, a practice exercise and a quick recall.
Part of the free React course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Practice
What You've Learned So Far
JSX In Depth — JSX is sugar for createElement objects; {} embeds expressions; attributes are camelCase; return one root.
Props & One-Way Data Flow — read-only inputs flow down; events flow up via callbacks; children wraps content.
Fragments — group siblings with <>...</> and add zero DOM nodes.
How Rendering Works — render builds a virtual DOM; reconciliation diffs it; only changes are committed; a re-render is not always a DOM update.
Styling — className , camelCase inline style objects, scoped CSS Modules, conditional classes.
Strict Mode — dev-only double-invoke surfaces impurity and missing cleanup.
useLayoutEffect vs useEffect — before paint vs after paint; measure-and-adjust layout in the pre-paint hook.
Immutable State Updates — never mutate; copy with spread; add/remove/update arrays with spread/filter/map.
🛠️ Build Challenge: A Tiny To-Do Model
Implement four pure, immutable helpers for a to-do list, then run the three steps. None of your helpers may mutate the list they receive — each returns a brand-new array. This mirrors exactly how you would update React state.
1. addTodo(list, text) — append { id, text, done: false } using spread.
2. toggleTodo(list, id) — map the list, flipping done on the match.
3. removeTodo(list, id) — filter out that id.
4. summary(list) — return "DONE/TOTAL done" .
🧩 Reorder Challenge
Order the lifecycle of one state update, the thread running through this whole track:
Common Errors (and the fix)
- Helper mutates the list. — Using push / splice breaks purity. Return a new array with spread/filter/map.
- Two siblings, no wrapper. — Group them in a fragment <>...</> .
- Reading props.x when it is undefined. — Add a default or guard; props are inputs you do not control.
- Side effect in render. — Keep render pure; move effects into useEffect with cleanup.
📋 Quick Reference
Idea
In one line
JSX
sugar for createElement; one root
Props
read-only, flow down; events flow up
Rendering
diff then commit only changes
Effects
useEffect after paint; clean up
State
update immutably (new value)
🧠 Quick Recall
React.createElement calls returning plain element objects.
Down via props; events flow back up via callback props.
React compares by reference; a new value is how it detects the change and re-renders.
🔎 Predict-the-Output Self-Test
Guess each line before running it. This checks that reference equality and shallow copies really clicked.
📝 Checkpoint Quiz
1. Why must a component return one root element?
The return is a single expression compiling to one element. Group siblings in a fragment <>...</> .
2. A child needs to tell its parent a value changed. How?
The parent passes a callback prop; the child calls it. Data flows down, events flow up.
No. React diffs the new tree and commits only the changes; an unchanged tree leaves the DOM alone.
4. You write items.push(x) then setState and nothing updates. Why?
Same reference — React bails out. Pass a new array: [...items, x] .
5. When does useLayoutEffect run relative to paint?
Synchronously before paint (useEffect runs after). Use it only for measure-and-adjust layout.
6. Why does an effect sometimes run twice in development?
Strict Mode double-invokes (run, cleanup, run) to surface missing cleanup. It is dev-only.
Frequently Asked Questions
🎉 Checkpoint Complete
- ✅ Reviewed every React Fundamentals idea in one place
- ✅ Built immutable to-do helpers with spread, map, filter
- ✅ Confirmed references vs copies with the self-test
- ✅ Passed the checkpoint quiz on rendering, props, and effects
- ✅ Next lesson: useId — generate stable unique IDs in React
Practice quiz
What does JSX compile down to?
- Raw HTML strings inserted into the DOM
- Template literals evaluated at runtime
- React.createElement calls that return plain element objects
- A separate .html file loaded by the bundler
Answer: React.createElement calls that return plain element objects. JSX is syntactic sugar for React.createElement(...) calls, which return plain JavaScript objects describing the UI.
Why must a component's return contain a single root element?
- Because the return is one expression that compiles to one element; group siblings in a fragment
- Because React only renders the first element it finds
- Because multiple roots make the DOM slower
- Because className can only be applied to one node
Answer: Because the return is one expression that compiles to one element; group siblings in a fragment. A return is a single expression compiling to one element. Wrap multiple siblings in a fragment <>...</> to satisfy this.
How do props behave in React?
- They are mutable and can be reassigned by the child
- They flow up from child to parent automatically
- They are global and shared across all components
- They are read-only inputs that flow down from parent to child
Answer: They are read-only inputs that flow down from parent to child. Props are read-only. Data flows down via props; events flow back up via callback props.
A child needs to tell its parent that a value changed. What is the idiomatic way?
- Mutate the prop directly inside the child
- The parent passes a callback prop and the child calls it
- Use a global variable both can read
- The child re-renders the parent manually
Answer: The parent passes a callback prop and the child calls it. Data flows down, events flow up: the parent passes a callback prop, and the child invokes it to report the change.
What is a fragment used for?
- To group sibling elements while adding zero extra DOM nodes
- To add an extra wrapper div to the DOM
- To memoize a component
- To pass props to many children at once
Answer: To group sibling elements while adding zero extra DOM nodes. A fragment <>...</> groups siblings into one root without rendering any additional DOM node.
Does every re-render result in a DOM update?
- Yes, every render rewrites the entire DOM
- Only when state is an object
- No; React diffs the new tree and commits only the changes
- Only in production builds
Answer: No; React diffs the new tree and commits only the changes. React builds a virtual DOM, reconciles it against the previous tree, and commits only the differences. An unchanged tree leaves the DOM alone.
You call items.push(x) then setState, but nothing updates. Why?
- push is asynchronous
- The array reference is unchanged, so React bails out of the update
- setState only works with numbers
- You must call render() manually after push
Answer: The array reference is unchanged, so React bails out of the update. Mutating in place keeps the same reference. React compares by reference, so it skips the update. Pass a new array like [...items, x].
When does useLayoutEffect run relative to the browser paint?
- After paint, like useEffect
- Only on unmount
- It never runs in development
- Synchronously before paint
Answer: Synchronously before paint. useLayoutEffect runs synchronously before paint (useEffect runs after). Use it only for measure-and-adjust layout work.
Why does an effect sometimes run twice in development?
- Because of a bug in React
- Because Strict Mode double-invokes effects to surface missing cleanup
- Because the dependency array is empty
- Because useEffect always runs twice in every environment
Answer: Because Strict Mode double-invokes effects to surface missing cleanup. Strict Mode intentionally mounts, unmounts, and remounts in development (run, cleanup, run) to reveal effects that are missing cleanup. It is dev-only.
How do you apply an inline style object in JSX?
- style='color: red' as a plain string
- css={{ color: 'red' }}
- style={{ color: 'red' }} with a camelCased object
- inline-style='color: red'
Answer: style={{ color: 'red' }} with a camelCased object. Inline styles take an object with camelCased properties, e.g. style={{ backgroundColor: 'blue' }}. Use className for CSS classes.
Continue this course
- Previous: Immutable State Updates
- Next: useId