Rendering UI
Rendering UI explains React's initial render, createRoot, re-rendering from state and props, render and commit phases, reconciliation, purity, Strict Mode, identity, accessibility, and performance.
Learning Objectives
By the end of this lesson, you will be able to:
- Understand what rendering means in React.
- Understand the relationship between components, JSX, and rendering.
- Understand the React rendering lifecycle.
- Understand the initial render.
- Understand re-rendering.
- Understand how state changes trigger rendering.
- Understand how props can trigger rendering.
- Understand the role of
createRoot(). - Understand React's render and commit phases.
- Understand reconciliation at a high level.
- Understand why rendering does not mean direct DOM replacement.
- Understand conditional rendering.
- Understand list rendering.
- Understand nested component rendering.
- Understand render purity.
- Understand Strict Mode's development behavior.
- Debug rendering problems using React Developer Tools.
- Understand common rendering performance issues.
- Explain React rendering confidently in senior-level interviews.
Introduction
We've already learned:
React↓Vite↓Project Structure↓SPA↓React Developer Tools↓JSX
Now we need to understand what actually happens after we write JSX.
Consider:
function App() {return (<h1>Hello React</h1>);}
We know that JSX describes the UI.
But the important question is:
How does that JSX become something visible in the browser?
The high-level flow is:
Component↓JSX↓React Elements↓Render↓Reconciliation↓Commit↓DOM↓Browser
Understanding this flow is fundamental to becoming a strong React developer.
What Does "Rendering" Mean in React?
In React, rendering means React calls your components to determine what the UI should look like for the current props and state.
For example:
function Welcome() {return <h1>Welcome</h1>;}
When React renders Welcome, it evaluates the component and obtains the UI description:
Welcome↓<h1>Welcome</h1>
A useful mental model is:
Props + State↓Component↓JSX↓React Element Tree
Rendering is primarily about figuring out the next UI, not directly manipulating the DOM.
Rendering Does Not Mean "Update the DOM"
This is one of the most important concepts in React.
Beginners often think:
Render=Change DOM
That's not accurate.
A better model is:
Render↓Calculate desired UI↓Compare with previous result↓Commit required changes↓DOM
So:
Rendering determines what the UI should be. The commit phase applies necessary changes to the DOM.
The Initial Render
When your React application starts, React performs an initial render.
A typical Vite application contains something similar to:
import { StrictMode } from "react";import { createRoot } from "react-dom/client";import App from "./App";createRoot(document.getElementById("root")!).render(<StrictMode><App /></StrictMode>);
Let's understand this step by step.
The Root DOM Element
Your HTML might contain:
<body><div id="root"></div></body>
This element provides the location where React will manage the application UI.
Think of it as:
Browser DOM│└── #root│▼React App
React doesn't need to manage the entire HTML document.
It can manage a particular root.
createRoot()
Modern React uses:
import { createRoot } from "react-dom/client";
Then:
const rootElement =document.getElementById("root");const root = createRoot(rootElement!);
And finally:
root.render(<App />);
Conceptually:
DOM element↓createRoot()↓React Root↓render(<App />)
The root establishes the connection between React and the DOM container.
Rendering the App
When we write:
root.render(<App />);
we are telling React:
Render this React element tree into this root.
Conceptually:
<App />↓App component↓JSX↓React element tree↓DOM
For example:
function App() {return (<main><h1>TechLearningPro</h1><p>Learn modern engineering.</p></main>);}
React determines the corresponding UI.
Component Tree
Suppose:
function App() {return (<Layout><Header /><Main /><Footer /></Layout>);}
React can conceptually form:
App└── Layout├── Header├── Main└── Footer
During rendering, React evaluates the components and builds the corresponding element structure.
React Element Tree
Consider:
<h1>Hello React</h1>
This JSX is transformed into a JavaScript representation of the element.
Conceptually:
React Element{type: "h1",props: {children: "Hello React"}}
The exact internal representation is more complex, but this mental model is useful.
React uses this representation to determine what the UI should look like.
Rendering a Component
Consider:
function Greeting() {return <h1>Hello React</h1>;}
When React renders it:
React↓Call Greeting()↓<h1>Hello React</h1>↓React element
The important point:
React components are functions that React invokes during rendering.
Components Are Not Called Like Normal UI Code
You usually don't write:
const result = Greeting();
Instead:
<Greeting />
React controls when the component is evaluated.
This allows React to manage:
RenderingStateUpdatesEffectsContextScheduling
Initial Rendering Example
Consider:
function App() {return (<div><h1>React Course</h1><p>Learn rendering.</p></div>);}
The conceptual flow is:
root.render(<App />)↓App()↓JSX↓React Elements↓Reconciliation↓Commit↓DOM
The browser then displays:
React CourseLearn rendering.
Re-rendering
Initial rendering isn't the end.
React applications are dynamic.
Suppose:
function Counter() {const [count, setCount] = useState(0);return (<buttononClick={() => setCount(count + 1)}>Count: {count}</button>);}
Initial state:
count = 0
The UI is:
Count: 0
The user clicks.
setCount(1)
React schedules an update.
Then:
State change↓Component re-render↓New JSX result↓Reconciliation↓Commit necessary changes
The UI becomes:
Count: 1
What Causes a Re-render?
Common causes include:
State updateProps changeContext updateParent re-renderExternal store update
For example:
setCount(count + 1);
can cause the component to render again.
State Change Flow
The fundamental React loop is:
User Action↓Event Handler↓State Update↓React schedules update↓Component renders again↓New UI description↓Reconciliation↓DOM update
This is one of the most important diagrams in React.
Rendering With Props
Props can also affect rendering.
Consider:
function CourseCard({title}: {title: string;}) {return <h2>{title}</h2>;}
Parent:
<CourseCard title="React" />
Later:
<CourseCard title="Angular" />
The child needs to render based on the new prop value.
Conceptually:
Parent↓Props change↓CourseCard↓New JSX↓Updated UI
Parent Re-render
A common misconception is:
If a child has the same props, it can never render again.
Not necessarily.
If a parent renders:
function Parent() {const [count, setCount] = useState(0);return (<><button onClick={() => setCount(count + 1)}>{count}</button><Child /></>);}
the parent renders again when count changes.
By default, React may also evaluate the child as part of rendering that subtree.
Later we'll study optimization techniques such as:
React.memouseMemouseCallback
But first, understand the default rendering model.
Re-render Does Not Mean Everything Changes
Suppose:
Previous UI:<h1>React</h1>New UI:<h1>React</h1>
React can determine that there is no meaningful DOM change.
Therefore:
Component rendered↓Same output↓No DOM update required
This is why:
A render does not necessarily produce a DOM mutation.
Render Phase
React's rendering process can be conceptually divided into phases.
The first is the:
Render phase
During this phase, React determines what the next UI should look like.
Conceptually:
State / Props↓Render phase↓New React element tree
The render phase should be treated as pure.
Commit Phase
After React determines the necessary changes, it enters the:
Commit phase
This is where React applies necessary changes to the host environment, such as the browser DOM.
Conceptually:
Render phase↓Determine changes↓Commit phase↓DOM updates
Render vs Commit
Remember this distinction:
| Phase | Main Responsibility |
|---|---|
| Render | Determine what UI should look like |
| Commit | Apply necessary changes |
So:
Render ≠ DOM update
Instead:
Render+Commit=Updated UI
This distinction becomes extremely important when debugging performance.
Why Render Must Be Pure
React may render components more than once.
Therefore, rendering code should not perform side effects.
Bad:
function CoursePage() {localStorage.setItem("visited","true");return <h1>Courses</h1>;}
The problem is that writing to localStorage is a side effect.
Better:
function CoursePage() {useEffect(() => {localStorage.setItem("visited","true");}, []);return <h1>Courses</h1>;}
Effects are a separate concept we'll study deeply later.
What Is a Side Effect?
A side effect is work that interacts with something outside the component's pure calculation.
Examples:
API requestlocalStorage writeDOM manipulationSubscriptionTimerAnalytics event
Don't perform such operations directly during rendering.
Instead, React provides mechanisms such as:
useEffectevent handlersexternal APIs
depending on the requirement.
Rendering Should Be Deterministic
Ideally:
Same props+Same state=Same UI result
For example:
function Greeting({name}: {name: string;}) {return <h1>Hello {name}</h1>;}
If:
name = "Jagannath"
the component should consistently produce:
Hello Jagannath
This predictability is a major advantage of React's declarative model.
Conditional Rendering
Rendering can depend on state.
function Dashboard({isLoggedIn}: {isLoggedIn: boolean;}) {return (<main>{isLoggedIn? <UserDashboard />: <Login />}</main>);}
Conceptually:
isLoggedIn│├── true → UserDashboard│└── false → Login
React renders the UI corresponding to the current state.
Rendering Lists
React commonly renders arrays into UI.
const courses = [{ id: 1, title: "React" },{ id: 2, title: "Java" },{ id: 3, title: "Spring Boot" }];
Then:
<ul>{courses.map(course => (<li key={course.id}>{course.title}</li>))}</ul>
The rendering flow is:
Array↓map()↓React elements↓List UI
Why Keys Matter During Rendering
Consider:
Before:ABCAfter:ACD
React needs to understand the identity of each item.
Stable keys provide that identity:
key={course.id}
Conceptually:
A → sameB → removedC → sameD → new
Keys are particularly important during reconciliation.
Nested Rendering
Consider:
function App() {return <Dashboard />;}function Dashboard() {return (<main><Header /><CourseList /></main>);}
The rendering chain becomes:
App↓Dashboard├── Header└── CourseList
React evaluates the component hierarchy and determines the resulting UI tree.
Rendering Children
A component can receive children:
function Card({children}: {children: React.ReactNode;}) {return (<article className="card">{children}</article>);}
Usage:
<Card><h2>React</h2><p>Learn React rendering.</p></Card>
The child content becomes part of the rendered tree.
Rendering Text
React can render strings and numbers:
<h1>{title}</h1><p>{count}</p>
For example:
title = "React"count = 10
produces:
React10
But arbitrary objects aren't valid normal React children:
<p>{user}</p>
Instead:
<p>{user.name}</p>
Rendering null
A component can intentionally render nothing:
function AdminPanel({isAdmin}: {isAdmin: boolean;}) {if (!isAdmin) {return null;}return <section>Admin Panel</section>;}
When:
isAdmin = false
the component produces no visible UI.
Rendering false
This pattern is common:
{isAdmin && <AdminPanel />}
If:
isAdmin = false
React doesn't display the boolean value.
However, be careful with values such as 0:
{items.length && <List />}
If items.length is 0, you may end up rendering 0.
Prefer:
{items.length > 0 && <List />}
Rendering and Browser Paint
The complete process involves more than React.
A simplified model:
State↓React Render↓Reconciliation↓React Commit↓DOM↓Browser Layout↓Browser Paint↓Screen
This distinction matters when diagnosing performance.
A slow application may be caused by:
React renderingJavaScript computationDOM sizeLayoutPaintNetwork
React DevTools only gives you part of the picture.
React Reconciliation
Reconciliation is the process React uses to determine how the current rendered result differs from the previous one.
Conceptually:
Previous UI+New UI↓Reconciliation↓Required changes
For example:
Previous:<h1>Count: 1</h1>New:<h1>Count: 2</h1>
React identifies that the text needs to change.
Reconciliation Is Not Simply "Compare HTML"
React isn't simply comparing two HTML strings.
It works with React's element/tree representation and uses rules involving:
Element typeKeysPositionPropsComponent structure
This allows React to efficiently determine what needs to change.
We'll study reconciliation and the modern React rendering model in much more depth later.
Element Type Matters
Suppose:
<div>React</div>
becomes:
<section>React</section>
The element type changed:
div↓section
React treats this differently from simply changing text.
The type is one of the important inputs to reconciliation.
Stable Component Structure
Consider:
function App() {return (<main><CourseList /></main>);}
Then:
CourseList
continues to occupy the same conceptual position in the tree.
Stable structure and keys help React preserve appropriate component identity between renders.
Rendering and Component Identity
Consider:
<CourseCard key={course.id} />
React uses the key along with the surrounding tree structure to determine component identity.
This affects whether React can preserve things such as:
Component stateDOM nodesInput values
when list items change.
This is why incorrect keys can produce subtle bugs.
Example: Incorrect Keys
Suppose:
Before:ABC
Then:
After:XABC
If indexes are used as keys:
0 → X1 → A2 → B3 → C
React can interpret the identity differently than you intended.
With stable IDs:
A → AB → BC → CX → new
The second approach better represents item identity.
Rendering and State Preservation
React's component identity determines whether state is preserved.
For example:
<Counter />
If the same component remains in the same conceptual position, React can preserve its state across renders.
If the identity changes because the component type or key changes, React may reset that state.
This becomes very important in:
FormsTabsListsConditional UIRouting
Initial Render vs Re-render
Let's compare them.
Initial render
Application starts↓createRoot()↓root.render()↓Component tree evaluated↓DOM created/updated
Re-render
State/props/context change↓React schedules update↓Component tree evaluated as needed↓Reconciliation↓Commit changes
The two processes are related but not identical.
Does Every State Update Render the Entire Application?
Not exactly.
A state update doesn't mean React blindly recreates the entire DOM.
React determines which parts of the tree need to be evaluated and which changes need to be committed.
For example:
App├── Header├── CourseList└── Footer
If a local state update occurs inside:
CourseList
React doesn't necessarily need to update the DOM for:
HeaderFooter
Only the necessary parts of the rendered tree are ultimately committed.
Does Every Component Re-render?
This is more nuanced.
A parent rendering can cause React to evaluate descendants by default.
But React has mechanisms that can prevent unnecessary work.
Examples include:
React.memouseMemouseCallbackState placementComponent boundariesContext designExternal stores
Don't memorize these yet.
First understand:
Rendering is normal React behavior. Optimization comes after measuring.
React Strict Mode
Vite React projects often start with:
<StrictMode><App /></StrictMode>
Strict Mode enables additional development-only checks.
One behavior developers commonly notice is that certain render-related functions may appear to run more than once during development.
This is intentional.
It helps reveal code that incorrectly relies on rendering being executed exactly once.
Strict Mode Does Not Mean Production Double Rendering
A common misconception is:
React always renders components twice.
That's incorrect.
Strict Mode's extra checks are development-oriented behavior.
Don't remove Strict Mode simply because you see additional development behavior.
Instead, use it to identify code that isn't safe or pure during rendering.
Rendering With React Developer Tools
Remember the previous lesson.
If you have:
Dashboard└── CourseList├── CourseCard├── CourseCard└── CourseCard
React DevTools can help you inspect the component tree.
The Profiler can help you investigate:
Which components rendered?How often?How expensive?
This makes rendering behavior observable.
Debugging a Rendering Problem
Suppose:
I changed the course filter, but the UI isn't updating.
Use this workflow:
Filter changed↓Did state change?↓React DevTools↓Check state↓Did component render?↓Check props↓Check API/network↓Check derived data↓Check JSX condition
This is much better than randomly modifying code.
Example: State Not Updating
Consider:
const [course, setCourse] = useState({title: "React"});
Then someone does:
course.title = "Angular";setCourse(course);
This mutates the existing object.
React state should generally be updated immutably:
setCourse({...course,title: "Angular"});
This creates a new object reference.
The distinction between mutation, identity, and rendering will become very important later.
Rendering and Immutability
React development commonly follows the principle:
Don't mutate state directly.Create a new state value.
For example:
Incorrect:
courses.push(newCourse);setCourses(courses);
Better:
setCourses([...courses,newCourse]);
This makes state changes easier for React and developers to reason about.
Rendering and Derived Data
Suppose:
const [courses, setCourses] = useState<Course[]>([]);const [search, setSearch] = useState("");
You can derive:
const filteredCourses =courses.filter(course =>course.title.toLowerCase().includes(search.toLowerCase()));
Then:
return (<CourseListcourses={filteredCourses}/>);
The model is:
State├── courses└── search↓Derived Data↓JSX↓UI
Derived values should generally be calculated from current state rather than duplicated unnecessarily.
Rendering and API Data
A common enterprise flow is:
API↓State / Server Cache↓Component↓JSX↓Render
For example:
function CoursePage() {const {courses,loading} = useCourses();if (loading) {return <Loading />;}return (<CourseList courses={courses} />);}
The UI changes as the data state changes.
Loading → Success
Initially:
loading = truecourses = []
React renders:
Loading...
Then API response arrives:
loading = falsecourses = [...]
React renders again:
Course List
The lifecycle becomes:
Initial state↓Render Loading↓API response↓State update↓Render CourseList↓Commit UI changes
This is one of the most common rendering patterns in real applications.
Loading → Error
Similarly:
loading = true↓Loading UI↓API fails↓error state↓Error UI
For production components, think in terms of:
LoadingErrorEmptySuccess
rather than only:
Success
Rendering Performance
Rendering performance becomes important when applications become large.
For example:
Dashboard├── 10 charts├── 5 tables├── 1,000 rows├── filters└── notifications
A small state change can potentially trigger expensive work.
The right approach is:
Measure↓Identify bottleneck↓Understand cause↓Optimize↓Measure again
Not:
Add memo everywhere
Common Rendering Performance Techniques
Later we'll study each in depth.
Important techniques include:
Component decompositionState colocationReact.memouseMemouseCallbackList virtualizationCode splittingLazy loadingEfficient data fetchingCachingAvoiding unnecessary effects
But optimization should be evidence-driven.
Rendering and Large Lists
Suppose an API returns:
10,000 courses
Rendering all 10,000 rows can be expensive.
Instead, consider:
Server-side paginationORVirtualizationORIncremental loading
Conceptually:
10,000 records↓Only relevant subset↓React renders visible UI↓Browser
This becomes important in enterprise React applications.
Rendering and Virtualization
For very large lists:
10,000 rows
you might render only:
Visible rows+Small buffer
For example:
Viewport┌─────────────────┐│ Row 401 ││ Row 402 ││ Row 403 ││ Row 404 ││ Row 405 │└─────────────────┘Not all 10,000 DOM nodes.
This can dramatically reduce DOM work.
Rendering and Server-Side Pagination
Another approach:
GET /courses?page=1&size=50
Instead of:
GET /courses→ 10,000 records
The server returns only what the user needs.
This is often preferable for enterprise systems because it reduces:
Network payloadMemory usageRendering workDatabase response size
Rendering and URL State
Suppose:
/courses?page=2&search=react
The URL contains:
page = 2search = react
The component renders based on those values.
Conceptually:
URL↓Router↓State/Derived State↓JSX↓UI
This is especially useful for searchable and filterable applications.
Rendering and Accessibility
Rendering isn't only about visual output.
When React changes the UI dynamically, consider:
FocusScreen readersARIADocument titleKeyboard navigationLoading announcements
For example, if a modal appears:
State change↓Modal rendered↓Focus should move appropriately
Good rendering architecture considers accessibility from the beginning.
Rendering and Error Boundaries
Large React applications should also think about rendering failures.
Conceptually:
Application│├── Header├── Dashboard│ └── CourseWidget└── Footer
If a particular UI subtree fails, an Error Boundary can provide a fallback rather than allowing the entire user experience to fail.
Conceptually:
Error Boundary│▼CourseWidget│XError│▼Fallback UI
We'll study Error Boundaries separately.
A Complete Rendering Example
Consider:
function CoursePage() {const [courses, setCourses] = useState<Course[]>([]);const [loading, setLoading] = useState(true);useEffect(() => {loadCourses().then(data => {setCourses(data);setLoading(false);});}, []);if (loading) {return <p>Loading...</p>;}return (<ul>{courses.map(course => (<li key={course.id}>{course.title}</li>))}</ul>);}
The lifecycle is:
Component starts↓loading = true↓Render "Loading..."↓Effect starts API request↓API response↓setCourses(data)↓setLoading(false)↓Re-render↓Map courses↓Render list↓Commit DOM changes
This is real-world React rendering.
The Render Cycle
A useful simplified model:
┌──────────────┐│ Initial Load │└──────┬───────┘│▼Render│▼Commit│▼DOM│▼User Action│▼State Update│▼Render│▼Reconciliation│▼Commit│▼Updated DOM│└───────► User
This loop is the heart of React.
Important Correction: Render Is Not "Painting"
A browser ultimately paints pixels to the screen.
React's render phase does not paint pixels.
The simplified layers are:
React↓Determine UI↓Commit DOM↓Browser↓Layout↓Paint↓Compositing
Keeping these layers separate helps when analyzing performance.
React Rendering vs Browser Rendering
Don't confuse:
React rendering
Component↓React elements↓Reconciliation
with:
Browser rendering
DOM↓Style calculation↓Layout↓Paint↓Composite
Both are involved in getting pixels onto the screen.
Interview questions & answers
Interview preparation
14 questions grouped by difficulty — expand any card for a model answer and follow-up probe.
Beginner
1What is rendering in React?
BeginnerModel answer
Rendering is the process where React evaluates components using their current props and state to determine what the UI should look like.
2What is the initial render?
BeginnerModel answer
The initial render is the first time React evaluates the application's component tree and commits the resulting UI to the DOM.
3What causes a React component to re-render?
BeginnerModel answer
Common causes include state updates, changed props, context updates, parent renders, and updates from external stores.
4Does re-rendering mean the entire DOM is recreated?
BeginnerModel answer
No.
React determines what changed and commits only the necessary DOM updates.
Intermediate
5Explain render phase and commit phase.
IntermediateModel answer
During the render phase, React evaluates components and determines the next UI representation.
During the commit phase, React applies the necessary changes to the DOM or other rendering environment.
6Why should rendering be pure?
IntermediateModel answer
React may evaluate rendering logic multiple times, so rendering should produce the UI from its inputs without causing side effects.
Side effects should be handled through appropriate mechanisms such as event handlers or effects.
7What is reconciliation?
IntermediateModel answer
Reconciliation is the process React uses to compare the previous rendered result with the new result and determine what changes need to be committed.
8Does every render cause a DOM update?
IntermediateModel answer
No.
React may render a component and determine that there are no necessary DOM changes.
Advanced
9What happens when state changes?
AdvancedModel answer
A state update schedules React to update the affected component tree.
React evaluates the relevant components again, produces a new UI representation, reconciles it with the previous result, and commits the necessary changes to the DOM.
10How would you debug unnecessary renders?
AdvancedModel answer
I'd use React DevTools and the Profiler to measure which components render and how expensive they are.
Then I'd investigate parent renders, state placement, prop identity, context updates, and derived computations before applying targeted optimizations.
11Why is immutability important in React state?
AdvancedModel answer
Creating new state values makes changes explicit and gives React and related optimization mechanisms clear identity changes to work with.
Direct mutation can lead to difficult-to-reason-about updates and stale UI.
12How would you explain React rendering to a junior developer?
AdvancedModel answer
I'd explain it as: React takes the current state and props, evaluates the components to determine the desired UI, compares that result with the previous one, and then updates only what needs to change in the DOM.
13How would you optimize a slow React rendering path?
AdvancedModel answer
First I'd measure it using React Profiler and browser performance tools.
Then I'd identify whether the bottleneck is component rendering, expensive calculations, large lists, network/data processing, or browser layout and paint.
Based on the actual bottleneck, I'd apply techniques such as state colocation, memoization, virtualization, code splitting, or data-fetching improvements.
14Does React guarantee that a component renders only once?
AdvancedModel answer
No.
Components can render multiple times as application state, props, context, or other dependencies change.
Development Strict Mode can also intentionally invoke certain logic more than once to expose unsafe patterns.
Senior Scenario Question
Interviewer:
A React page is slow whenever the user changes a filter. How would you investigate?
A strong answer:
I wouldn't immediately add memoization. I'd first reproduce the issue and measure it using React DevTools Profiler and browser performance tools. I'd identify which components are rendering and which operations are expensive. Then I'd check whether the filter is triggering unnecessary API calls, expensive calculations, large list rendering, or unnecessary child renders. If it's a large dataset, I'd consider server-side filtering or pagination and possibly virtualization. If it's unnecessary rendering, I'd review state placement, prop identity, context usage, and memoization. After making the change, I'd profile again to verify that the optimization actually improved the problem.
That answer demonstrates engineering maturity because it focuses on measurement and root cause, not just React keywords.
Practical Exercise
Create this component:
import { useState } from "react";function Counter() {const [count, setCount] = useState(0);return (<section><h1>Counter</h1><p>Count: {count}</p><buttononClick={() =>setCount(count + 1)}>Increment</button></section>);}
Now observe:
Initial
count = 0↓Render↓Count: 0
Click
setCount(1)↓Render↓Count: 1
Click again
setCount(2)↓Render↓Count: 2
Use React Developer Tools to observe the component.
Then use the Profiler to record the interaction.
Advanced Exercise
Create:
function Parent() {const [count, setCount] = useState(0);return (<><buttononClick={() =>setCount(count + 1)}>{count}</button><Child /></>);}function Child() {return (<div>Child Component</div>);}
Use React DevTools to observe the component tree.
Then ask:
When Parent state changes:↓Does Parent render?↓Does Child render?↓Does Child's DOM change?
This exercise will prepare you for:
React.memoMemoizationComponent boundariesState colocationRendering optimization
Advanced Exercise — List Rendering
Create:
const courses = Array.from({ length: 1000 },(_, index) => ({id: index,title: `Course ${index}`}));
Render:
<ul>{courses.map(course => (<li key={course.id}>{course.title}</li>))}</ul>
Then profile the component.
Ask:
What happens with 10 items?What happens with 1,000?What happens with 10,000?
This introduces the real-world problem of large-list rendering.
Rendering Architecture
At the application level:
React Application│▼State / Props│▼Component Tree│▼JSX│▼React Element Tree│▼Render Phase│▼Reconciliation│▼Commit Phase│▼DOM│▼Browser Rendering│┌─────────┴─────────┐▼ ▼Layout Paint│ │└─────────┬─────────┘▼Screen
This is the architecture you should keep in your head.
Final Mental Model
Memorize this:
STATE / PROPS│▼COMPONENT│▼JSX│▼REACT ELEMENTS│▼RENDER PHASE│▼RECONCILIATION│▼COMMIT PHASE│▼DOM│▼BROWSER PAINT│▼SCREEN
And when the user interacts:
USER ACTION↓EVENT HANDLER↓STATE UPDATE↓RENDER↓RECONCILIATION↓COMMIT↓UPDATED UI
The most important principle is:
React rendering is not "React rewriting the HTML." React evaluates components to determine the desired UI, reconciles that result with the previous one, and commits only the necessary changes to the rendering environment.
This distinction will become the foundation for understanding Virtual DOM, reconciliation, state, props, hooks, component lifecycle, and React performance.