Skip to main content

Two kinds of components

As your app grows, you’ll naturally split components into two roles:
UserDashboard knows about APIs and state. UserList and UserCard know nothing about where data comes from — they just display what they receive. This separation makes presentational components reusable across your app.
You don’t need to force every component into one category. This is a guideline, not a rule. The goal is simple: push state management up and keep display components focused on rendering.

Lifting state up

When two sibling components need the same data, move the state to their shared parent:
UserPage owns the state. SearchBar updates it via a callback. UserList reads the filtered result. Neither child knows about the other — the parent coordinates everything.
“Lifting state up” is the answer to “how do sibling components share data?” Move the state to the nearest common parent. The parent passes data down via props and receives updates via callback props.

Callback props — child-to-parent communication

Props flow down (parent → child). For the reverse direction, pass a function as a prop:
The data flow is clear: TodoApp owns all the state and logic. Children communicate back by calling the callback props (onAdd, onToggle, onDelete). No child modifies state directly.

A full composition example

Here’s a realistic page that combines everything — fetch, state, forms, lists, and composition:
Notice the pattern: DashboardPage handles all API calls and state. CreateUserForm has local state for the input fields, but the actual “create” logic lives in the parent. UserTable is pure display.

Rules of thumb

  1. State goes in the highest component that needs it — not higher, not lower
  2. If two components need the same data — lift the state to their parent
  3. Smart components fetch and manage — presentational components display
  4. Callback props for child → parent — never modify parent state directly from a child
  5. Local state is fine for UI-only state — form inputs, open/closed toggles, hover states
Don’t try to make every component “dumb.” Form components naturally need local state for their inputs. The goal isn’t zero state in children — it’s putting shared state in the right place and keeping API logic in smart components.

What’s next?

You’ve learned the React essentials — components, props, state, effects, conditional rendering, lists, forms, and composition. These 8 concepts cover 90% of what you’ll do in React. Now let’s put it all together. In the next section, you’ll connect your React frontend to a FastAPI backend and build a complete full-stack application.

Full-stack project structure

Organize a project with a React frontend and FastAPI backend