šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Thinking in React: From Design to Component Tree

A step-by-step guide to the Thinking in React methodology: component hierarchy, static builds, minimal state, and inverse data flow.

⚔ Total XP: 0|šŸ’» react XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

The five-step process.

Quick Quiz //

What is the very first step in the Thinking in React process?


šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Turning a design or feature request into a well-structured React app is a design skill, not just a syntax one. This lesson walks through the five-step process: breaking UI into a hierarchy, building a static version, finding minimal state, placing state correctly, and wiring inverse data flow.

1Design, Not Just Syntax

Knowing hooks and JSX syntax is not the same skill as designing a component tree from a mockup or requirement. Thinking in React is a repeatable five-step process for that design work: breaking the UI into components, building it statically, finding minimal state, deciding where state should live, and adding inverse data flow.

2Step 1: Break the UI into a Component Hierarchy

Looking at a design, draw a box around every distinct piece of UI, then a box around groups of related boxes — each box becomes a candidate component. A useful heuristic is that if a piece of UI represents one part of your data model, it usually deserves to be its own component.

3Step 2: Build a Static Version First

The entire UI should first be built using only props flowing down the tree, with zero state and zero interactivity. This isolates structural correctness from the added complexity of state management, making bugs in either layer easier to identify separately.

4Step 3: Find the Minimal Set of State

For every piece of data in the app, ask whether it stays constant over time and whether it can be computed from other existing props or state — if either is true, it isn't state. What remains, data that genuinely changes and can't be derived, forms the minimal set of true state the app needs.

5Step 4: Decide Where State Should Live

For each piece of state, identify every component that renders based on it, then find their closest common ancestor in the tree — that's where the state should be declared. State should sit as low in the tree as possible while still being accessible to every component that depends on it.

6Step 5: Add Inverse Data Flow

Because state flows down through props but user interactions happen in components lower in the tree, the component that owns the state must pass a setter function down as a prop. Children call that setter to trigger updates to state living above them, completing the loop: data flows down, events flow up.

7Step-by-Step Breakdown

Design, Not Just Syntax. You know the hooks. You know JSX. The harder skill is turning a design mockup or a feature request into a well-structured component tree before you write a single line of code. 'Thinking in React' is a five-step process for doing exactly that, and it's one of the most useful mental models a React developer can have.

Step 1: Break the UI into a Component Hierarchy. Look at your design and draw boxes around every piece of UI, then boxes around groups of boxes. Each box is a candidate component. A good rule of thumb: if a piece of UI represents one part of your data model, it's probably its own component. Name each box, and you've sketched your component tree before writing any code.

Step 2: Build a Static Version First. Build the entire UI using props only, passing data down through the tree, with zero interactivity and zero state. This forces you to focus purely on structure and rendering correctness before dealing with the added complexity of state changes. Resist the urge to add useState at this stage, even if it's tempting.

Why does 'Thinking in React' recommend building a fully static version before adding any state?

  • →It separates structural correctness from the added complexity of state
  • →It's simply faster to type than useState calls

Step 3: Find the Minimal Set of State. Now identify what actually needs to be state. For each piece of data, ask: does it stay constant over time? If so, it's not state. Can it be computed from other props or state? If so, it's not state either — it's derived. What remains, the data that truly changes and can't be derived, is your minimal state.

Step 4: Decide Where State Should Live. For each piece of state, find every component that renders based on it, then find their closest common parent component. Put the state there. If it's unclear where the common parent should live, a temporary intermediate component is fine — but always place state as low in the tree as possible while still being shared by everything that needs it.

Two sibling components, SearchBar and ProductTable, both need the current search text. Where should that state live?

  • →In their closest common parent component
  • →Duplicated separately inside each sibling

Step 5: Add Inverse Data Flow. State flows down through props, but user input happens in child components lower in the tree. The parent that owns the state must pass a setter function down as a prop, so the child can call it to update the state that lives above it. This closes the loop — data flows down, and events flow up.

Mastery Achieved. You now have a repeatable process for turning any design or requirement into a well-structured React app: break the UI into a hierarchy, build it static, find the minimal state, place that state at the right level, and wire up inverse data flow. Next, you'll go deeper into component composition — the techniques for keeping that hierarchy flexible as it grows.

Level Up šŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

This is a design methodology, not a browser API.

FirefoxSupported

Fully applicable.

SafariSupported

Fully applicable.

EdgeSupported

Fully applicable.

Accessibility (A11y)

1Design the Component Hierarchy Around Semantic Structure Too

When breaking a design into components, consider not just visual grouping but the underlying semantic HTML structure (landmarks, headings, lists) so the resulting component tree naturally produces accessible markup.

SEO Implications

  • 1

    A Clean Component Hierarchy Maps Naturally to Server/Client Boundaries

    A well-designed, single-responsibility component tree makes it far easier to decide which pieces should be Server Components versus Client Components, directly affecting how much content ships as indexable server-rendered HTML.

Best Practices

Resist Adding State During the Static Build Step

Even when it's tempting to reach for useState while building the static version, hold off — finishing the static structure first makes it much easier to identify exactly which values later need to become real state.

Re-derive Rather Than Duplicate

If a value can be computed from state or props you already have, compute it inline during render instead of storing a duplicate copy in its own state — duplicated state is a common source of out-of-sync UI bugs.

Frequent Bugs

THE BUG

Two sibling components show search results that fall out of sync with each other.

THE FIX

The search state was likely duplicated in each sibling instead of being lifted to their closest common parent and passed down as props — shared data should have exactly one source of truth.

THE BUG

A component can't update a value that visually lives in a component above it in the tree.

THE FIX

Inverse data flow is missing — the parent needs to pass a setter function down as a prop so the child can call it, rather than trying to modify the parent's state directly.

Real-World Examples

Designing a Filterable Product Table

Given a mockup of a search bar above a product table, the design breaks into FilterableProductTable (root), SearchBar, and ProductTable with ProductRow children. The search text is the only true state — it changes and can't be derived — and it lives in FilterableProductTable since both SearchBar and ProductTable depend on it.

function FilterableProductTable({ products }) {
  const [searchText, setSearchText] = useState('');
  const filtered = products.filter(p => p.name.includes(searchText));
  return (
    <>
      <SearchBar searchText={searchText} onSearchTextChange={setSearchText} />
      <ProductTable products={filtered} />
    </>
  );
}

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Adding useState during the static-build step, before identifying minimal state

// Premature function ProductRow({ product }) { const [name, setName] = useState(product.name); // unnecessary state } // Correct: static first function ProductRow({ product }) { return <tr><td>{product.name}</td></tr>; }

The Solution //

Jumping straight to state before finishing a props-only static version often leads to state being declared for values that could simply be derived. Finish the static pass first, then apply the minimal-state test to each remaining value.

The Error //

Lifting state all the way to the app root 'just in case', instead of to the closest common ancestor

// Too high: App re-renders for every keystroke function App() { const [searchText, setSearchText] = useState(''); } // Correct: lives in the closest shared parent function FilterableProductTable() { const [searchText, setSearchText] = useState(''); }

The Solution //

Lifting state further than the closest shared ancestor of the components that need it causes unrelated parts of the tree to re-render and makes the data flow harder to trace. Place it at the lowest common ancestor instead.

Lesson Glossary

[01]Component Hierarchy

The nested tree structure of components derived by breaking a UI design into boxes and sub-boxes.

Code Preview
Parent > Child > Grandchild

[02]Static Version

A first implementation pass built purely from props, with zero state and zero interactivity.

Code Preview
Props only, no useState

[03]Minimal State

The smallest set of data that changes over time and cannot be derived from other props or state.

Code Preview
Cannot be computed elsewhere

[04]Common Ancestor

The closest shared parent of all components that need access to a given piece of state.

Code Preview
Lowest shared parent

[05]Inverse Data Flow

Passing a setter function down as a prop so a child can trigger updates to state owned by an ancestor.

Code Preview
onChange={setValue}

Continue Learning