React / Components and state / Lesson 1
React rendering and a reproducible setup
Understand components as UI descriptions, distinguish React from its host tools, and make the execution context explicit.
On this page
Lesson goals
- React describes a tree
- A component is a function with constraints
- Observe committed results
React describes a tree
React is a library for describing interfaces through components. A component computes a description from inputs; React coordinates rendering that description through a renderer such as React DOM. The browser still supplies HTML semantics, CSS layout, events, and accessibility behavior. React does not automatically provide routing, deployment, authentication, or a database. A framework can coordinate those concerns and may own the application entry point. Choose that environment deliberately instead of assuming a component file alone is a complete application. Begin by predicting the visible tree for fixed inputs before adding state or external connections.
Define the host project contract
Course examples are App.jsx component modules using package imports and JSX. They require a reviewed React project with a JSX-capable build tool, compatible react and react-dom packages, an HTML root container, and an entry module using createRoot from react-dom/client. A framework may supply this setup instead. The modules are marked non-runnable because they are not standalone browser documents or Node scripts. Local verification bundles them inside an isolated synthetic host rather than contacting a CDN. React 18.3.1 is the available test runtime; current React 19 documentation informs the explanations, with newer server features distinguished explicitly.
A component is a function with constraints
The first example exports a capitalized component that returns a heading and paragraph. Capitalization distinguishes user components from lowercase host tags in JSX. Rendering should be a pure calculation: do not modify a shared object, subscribe to a service, or write storage while producing the tree. React may render again, restart work, or discard a render before committing it. A component’s function call count is therefore not an application event count. Keep observable actions in event handlers and required external synchronization in Effects, introduced later. The useful contract is the resulting interface for its inputs, not a promised number of internal calls.
export default function App() {
return <main><h1>Workshop</h1><p>Build a meaningful interface.</p></main>;
}
Workshop
Build a meaningful interface.
A pure component returns a semantic document fragment. The host mounts App through a modern React DOM root.
Compose small descriptions
The second example reuses a small Notice component twice. Each occurrence belongs to a different position in the rendered tree; extracting a component does not create shared state by itself. Composition gives a name to a meaningful responsibility and lets the parent describe the larger page at a useful level. Avoid extracting every wrapper merely to increase component count. A reusable component should have a clear input and semantic role. The resulting DOM must still have appropriate headings and landmarks; abstraction does not exempt it from ordinary HTML rules or fix invalid nesting.
function Notice({ children }) { return <section>{children}</section>; }
export default function App() {
return <main><h1>Notes</h1><Notice><h2>Prepare</h2><p>Read first.</p></Notice><Notice><h2>Practice</h2><p>Try locally.</p></Notice></main>;
}
Notes
Prepare
Read first.
Practice
Try locally.
Two component occurrences produce two independent sections in source order. No network or state is involved.
Observe committed results
Inspect the visible page and accessibility tree after React commits, and use developer tools to trace props and state where available. Code immediately after root.render is not a reliable place to assert that the DOM has already updated; tests should use the renderer’s supported coordination. Development Strict Mode intentionally probes certain behavior and can expose missing cleanup or impure rendering. Do not disable it merely because a console message appears twice. Record runtime, build mode, entry point, and minimal source when reporting a defect. Keep package changes separate from the diagnosis until evidence identifies a compatibility issue.
Common errors and fixes
A JSX file fails when opened directly
- Why it happens
- The source requires package resolution and JSX transformation.
- How to fix it
- Use the documented host and build context.
- Prevent it next time
- Record the execution model with each example.
A lowercase component is treated as a host tag
- Why it happens
- JSX capitalization does not identify the custom component.
- How to fix it
- Use a capitalized component name.
- Prevent it next time
- Review imports and JSX names together.
Rendering triggers duplicate external work
- Why it happens
- An impure render performs effects directly.
- How to fix it
- Move actions to handlers or justified synchronization.
- Prevent it next time
- Test under development Strict Mode.
Check your understanding
1. What belongs to React and what belongs to a router or framework when a URL selects a page?
Show worked solution
React renders the chosen component tree. The routing integration interprets navigation, loads route data where designed, and coordinates history or server handling. A framework may also build and deploy those pieces. Document the chosen boundaries instead of attributing every behavior to React itself.
2. Why is a console line during render an unreliable count of user actions?
Show worked solution
React can repeat or abandon rendering, and development checks can invoke calculations again. An action belongs to the event or transaction boundary that actually owns it. Count a deliberate handler result or persisted operation, not incidental component evaluation.
Key takeaways
- Components describe UI under a host environment.
- Keep rendering pure and semantics intact.
- Test committed behavior rather than call counts.