Skip to content
WANCODE
BM

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

  1. State — what does the component remember? (topics, draft, seconds)
  2. Effects — what runs after render, and what values does it capture?
  3. Handlers — does every update create new data, or modify the old data in place?
  4. JSX — do lists have stable keys? Does anything render from data that might be missing?
React re-renders when state changes to a new value. Same object in → no re-render.

Red flag 1: mutating state

What the assistant wrote

JSX
topics.splice(index, 1); // changes the old array
setTopics(topics);        // same array → React skips the update

What a reviewer ships

JSX
setTopics(topics.filter((t) => t.id !== id)); // new array

push, 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

JSX
useEffect(() => {
  const timer = setInterval(() => {
    setSeconds(seconds + 1); // "seconds" is always 0 here
  }, 1000);
  return () => clearInterval(timer);
}, []);

What a reviewer ships

JSX
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

Q1

A generated handler does todo.done = true; setTodos(todos);. What happens?

Q2

Which is the best key for a list of topics loaded from a database?

Q3

Why did setSeconds(seconds + 1) inside setInterval stop at 1?

What you learned

  • Read components in order: state → effects → handlers → JSX.
  • Never mutate state; build new arrays/objects with filter, map and 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.
Preview

Console output from your code appears here.

Step 1 of 3