Reading a Generated React Component
18 minIntermediateReact
In this lesson
- ▸Read a component in a fixed order: state, effects, handlers, JSX
- ▸Recognise three bugs assistants often produce: mutating state, missing keys, stale closures
- ▸Confirm each fix by its behaviour, not just by how the code looks
The big idea
Generated React code usually renders fine on first load. The bugs hide in what happens next: an update that doesn't re-render, a list that reuses the wrong row, an effect that remembers an old value.
The component in the editor was "generated" for a simple prompt: a study planner with a topic list and a session timer. It looks tidy and it renders. Before reading on, try it: tick a box, remove a topic, watch the timer.
Read in a fixed order
- State — what does the component remember? (
topics,draft,seconds) - Effects — what runs after render, and what values does it capture?
- Handlers — does every update create new data, or modify the old data in place?
- JSX — do lists have stable
keys? Does anything render from data that might be missing?
Red flag 1: mutating state
What the assistant wrote
topics.splice(index, 1); // changes the old array
setTopics(topics); // same array → React skips the updateWhat a reviewer ships
setTopics(topics.filter((t) => t.id !== id)); // new arraypush, splice, sort, reverse and obj.x = … all modify in place. React compares the old and new state by reference, so the update is ignored — until something else re-renders and the change "randomly" appears.
Red flag 2: missing or unstable keys
Without a key, React matches list items by position. Remove the first topic and the second topic is drawn into the first row's DOM — including that row's checkbox. The console warns about it (Each child in a list should have a unique "key" prop), but generated code often ships with the warning ignored. Using the array index as the key has the same problem. Use a stable id from the data.
Red flag 3: stale closures in effects
What the assistant wrote
useEffect(() => {
const timer = setInterval(() => {
setSeconds(seconds + 1); // "seconds" is always 0 here
}, 1000);
return () => clearInterval(timer);
}, []);What a reviewer ships
useEffect(() => {
const timer = setInterval(() => {
setSeconds((s) => s + 1); // always uses the latest value
}, 1000);
return () => clearInterval(timer);
}, []);The effect runs once ([]), so its callback captured seconds from the first render forever. A functional update asks React for the current value instead.
Good news: the generated code also did several things right — preventDefault() on submit, trimming input, a spread for adding, and a cleanup function for the interval. Reviewing means noticing both.
Click Remove on a topic. Nothing happens — then, a moment later, the timer ticks and the list suddenly changes. That delay is the classic sign of mutated state. Rewrite removeTopic so it creates a new array instead of changing the old one.
Checks
- Clicking Remove updates the list immediately
- The topic count updates too
Check understanding
What you learned
- ✓Read components in order: state → effects → handlers → JSX.
- ✓Never mutate state; build new arrays/objects with
filter,mapand spread. - ✓Lists need stable keys from the data — and console warnings are review findings.
- ✓Callbacks in effects capture old values; use functional updates or correct dependencies.
Console output from your code appears here.