← Back to React
Lesson 2 · React Fundamentals

Why React?

Declarative UI, component reuse, and what you give up for them.

Beginner30 min

What you will be able to do

  • Explain why keeping a growing UI in sync by hand becomes hard
  • Describe how declarative UI removes that coordination work
  • Build one reusable component and render it with different data
  • Split a large screen into small, composed components
  • List what React gives you and what it leaves to other tools
  • Name the trade-offs of choosing React, and when they are not worth it

The idea, in plain English

Lesson 1 showed the idea on a single counter: describe the UI for the current state, and React updates the page. On one counter that is a nicety. This lesson is about why it becomes a necessity as an app grows - and what it costs you.

Take one action on a learning platform: a learner completes a lesson. The lesson row, the module progress, the course progress, the dashboard, an achievement badge, and a notification all need to change. Written by hand, that is a chain of updateLesson(), updateModuleProgress(), updateCourseProgress() calls, and every new screen adds another one to remember. Forget one, and the page quietly disagrees with itself.

React removes that chain. Each of those pieces describes itself from the same data, so when the data changes they all follow. You stop asking "which elements do I need to change?" and start asking "what should the screen look like now?" - and that shift is the single biggest reason React exists.

The second reason is reuse. A CourseCard written once can show React, Node.js, and Python by being given different data, and a course page can be composed from small pieces - a header, a module list, a progress bar - each with one job.

None of that is free. React brings a build step, a toolchain, and a set of new concepts, and it does not make an app fast or well-structured on its own. For a mostly static page it is overhead with no payoff. Choosing it well means knowing both columns of that ledger.

Worked example: Rewriting a jQuery-style progress widget as a React component.

The coordination problem

Direct DOM updates are fine one at a time: set a title, set a percentage, disable a button. The trouble starts when several parts of the page depend on the same piece of data, because each of them needs its own update code - and that code has to run in the right place every time the data changes.

A search box that filters courses, a selection that changes the title, description, lesson count, progress, sidebar, breadcrumb, and URL - each change fans out across the page. The work is not in any single update; it is in remembering all of them.

That is the problem React is built for: making the page a function of the data, so there is nothing to remember.

Declarative, briefly revisited

Lesson 1 covered the core distinction; one table is enough here. Imperative code says how to change the page. Declarative code says what the page should be.

A login switch shows it well. Imperatively, you find the heading and the button and swap their contents on click. Declaratively, the component simply says: if loggedIn, show a welcome; otherwise show a Login button. There is no switching code at all - the state decides.

Imperative against declarative
What you writeImperative: how to change the page. Declarative: what the page should be.
Who coordinates updatesImperative: you. Declarative: React.
In codeImperative: element.textContent = user.name. Declarative: <h1>{user.name}</h1>.
As the UI growsImperative: more update paths to keep in step. Declarative: components describe themselves.

Reuse: one component, many uses

Without components, a styled button is copied into every place it appears, and a change to it means finding every copy. A Button component puts that structure in one place; each use supplies only what differs - here, its label, passed as children.

The same goes for a whole card. One CourseCard, given title, lessons, and level, can render every course on the platform. You do not want ReactCourseCard, NodeCourseCard, and PythonCourseCard - you want one component and different data.

The values passed in are called props. They get a full lesson in Module 2; for now, read them as "the data this particular use of the component shows".

Tip: If you are about to copy a component and change a few words, that is the sign those words should become props.

Composition: small pieces with one job each

A course page does not have to be one component. It can be a CourseHeader, a CourseDescription, a ModuleList of Module components, and a CourseProgress - each small enough to understand, test, and change on its own.

The payoff shows up when something breaks. A bug in the progress bar sends you straight to CourseProgress, not into a 1,500-line file. Small components help maintenance, reuse, testing, collaboration, and debugging all at once.

What React gives you, and what it does not

React gives you a programming model: components, props, state, declarative rendering, and composition. Those five ideas are most of what this course builds on.

It does not give you a backend, a database, authentication, routing, global state, payments, or hosting. Real apps pair React with other tools - React Router, Redux or TanStack Query, a REST or GraphQL API, a server such as Node.js and Express, and a database such as PostgreSQL. Which ones depends on the app.

Yours from React, and yours to add
ComponentsFrom React. Reusable pieces of UI.
Props and stateFrom React. Data passed in, and data a component owns.
Declarative renderingFrom React. UI described from data, DOM updated for you.
RoutingNot included. Usually React Router, or a framework such as Next.js.
Server data and global stateNot included. TanStack Query, Redux, or Context.
Backend, database, authNot included, and not the job of a UI library at all.

What you give up

A plain page needs HTML, CSS, and JavaScript. A React app adds Node.js, npm, JSX, a bundler, a build process, and usually routing and testing setup. For a small or mostly static site, that is complexity with nothing to show for it.

There is a learning curve. A ten-line component can already involve functions, props, state, JSX, conditional rendering, event handling, and hooks - which is why React feels harder than plain JavaScript at first.

And React guarantees neither speed nor good structure. Unnecessary renders, large bundles, and slow network calls are all possible in React, and so is a 2,000-line component. React gives you the tools; the design is still yours.

Watch out: "React makes apps fast" is a myth. React makes UI updates manageable. Performance is a design choice - the React Performance module covers it.

Syntax and examples

The same data, updated by hand
// Each piece of the page is found and changed separately... document.querySelector('#title').textContent = 'React Course'; document.querySelector('#progress').textContent = '35%'; document.querySelector('#complete').disabled = true; // ...and one user action has to remember every one of them. function onLessonCompleted() { updateLesson(); updateModuleProgress(); updateCourseProgress(); updateDashboard(); updateAchievement(); updateNotification(); // forget one, and the page disagrees with itself }
A login switch - imperative
const message = document.querySelector('#message'); const button = document.querySelector('#button'); button.addEventListener('click', () => { message.textContent = 'Welcome!'; button.hidden = true; // and remember to hide the button too });
The same switch - declarative
function Welcome({ loggedIn }) { // No switching code: the data decides what is shown. return <div>{loggedIn ? <h1>Welcome!</h1> : <button>Login</button>}</div>; }
One Button instead of a hundred copies
function Button({ children }) { return <button className="primary-button">{children}</button>; } function Toolbar() { return ( <div> <Button>Save</Button> <Button>Submit</Button> <Button>Continue</Button> </div> ); }
One CourseCard, three courses
function CourseCard({ title, lessons, level }) { return ( <article> <h2>{title}</h2> <p>{lessons} lessons</p> <p>{level}</p> <button>Start Learning</button> </article> ); } function CourseList() { return ( <div> <CourseCard title="React" lessons={192} level="Beginner" /> <CourseCard title="Node.js" lessons={206} level="Intermediate" /> <CourseCard title="Python" lessons={75} level="Beginner" /> </div> ); }
Composing a page from small components
function CoursePage() { return ( <> <CourseHeader /> <CourseDescription /> <ModuleList /> <CourseProgress /> </> ); } // A bug in the progress bar? Open CourseProgress, not a 1,500-line file.
The worked example - a progress widget, DOM-manipulation style
let progress = 0; const progressElement = document.querySelector('#progress'); const button = document.querySelector('#complete'); button.addEventListener('click', () => { progress += 10; // State, DOM lookup, event handling, and DOM update - all this code's job. progressElement.textContent = `Progress: ${progress}%`; });
The same widget as a React component
import { useState } from 'react'; function Progress() { const [progress, setProgress] = useState(0); // progress -> UI. Nothing here finds or edits an element. return ( <div> <p>Progress: {progress}%</p> <button onClick={() => setProgress(progress + 10)}>Complete Lesson</button> </div> ); } export default Progress;

Tip: The question to carry into every React component: what should the UI look like for this state? If you find yourself asking which element to change, step back to the state.

Watch out: React still updates the DOM - it simply does it for you. Using React means you rarely write DOM code, not that the DOM stops mattering.

The five ideas React gives you

Each has its own lessons later in the course; this is the map.

Components

Reusable pieces of UI.

<CourseCard />
Props

Data given to a component by whoever uses it.

<CourseCard title="React" />
State

Data a component owns and can change.

const [count, setCount] = useState(0);
Declarative UI

The UI described from data.

<h1>{count}</h1>
Composition

Building bigger components out of smaller ones.

<CoursePage>...</CoursePage>

Try it yourself

The code does not change. Swap the content string and the program does something else entirely.

Add one more thing to update

“In the DOM-style progress widget, also show the progress in a second place - a heading, say. Count the lines you had to add. Then do the same in the React version.”

Find the copies

“Look at any page you use daily and find three things that look the same but show different data. Each is a component waiting to happen - what would its props be?”

Argue against React

“Pick a site that would be worse built in React. Write down what it would cost and what it would gain.”

What usually goes wrong

Copying a component to change its text

ReactCourseCard, NodeCourseCard, PythonCourseCard - three copies of one idea. The parts that differ belong in props.

✗ function ReactCourseCard() { /* ... */ }
function NodeCourseCard() { /* ... */ }
✓ <CourseCard title="React" lessons={192} />
<CourseCard title="Node.js" lessons={206} />
One enormous component

React makes splitting easy, but it does not do the splitting for you. A 2,000-line component is still possible - and still painful.

Assuming React makes an app fast

Unnecessary renders, large bundles, and slow requests are all possible in React. Speed comes from design, not from the library.

Expecting React to be the whole stack

Routing, server data, auth, and storage all come from elsewhere. Plan them from the start rather than discovering them later.

Using React where plain HTML would do

A mostly static page gains a build step and a bundle and nothing else. The trade-off only pays when the page is interactive and data-driven.

Best practices

  • Describe the UI from data, and change the data rather than the page.
  • When two components differ only in what they show, make one component with props.
  • Give each component one job, small enough to name clearly.
  • Compose pages from small components instead of growing one large one.
  • Choose React for its component and state model - not by default, and not for speed.

Practice

Write these yourself before opening anything. Getting them wrong first is most of how this sticks.

1.

Write a Button component that takes its label as children, and use it for Save, Submit, and Continue.

Show hint

Whatever sits between the opening and closing tags arrives as the children prop.

Show solution
function Button({ children }) { return <button className="primary-button">{children}</button>; } function Actions() { return ( <div> <Button>Save</Button> <Button>Submit</Button> <Button>Continue</Button> </div> ); }
2.

Rewrite element.textContent = user.name declaratively, inside a component that receives user.

Show hint

Describe the heading from the data instead of changing an element.

Show solution
function UserName({ user }) { return <h1>{user.name}</h1>; }
3.

Sketch a course page as a tree of four or five components, then write the top-level CoursePage.

Show hint

Name each part by its job - header, description, module list, progress.

Show solution
// CoursePage // ├── CourseHeader // ├── CourseDescription // ├── ModuleList // └── CourseProgress function CoursePage() { return ( <> <CourseHeader /> <CourseDescription /> <ModuleList /> <CourseProgress /> </> ); }
Coding challenge

A reusable course list

Render three courses from one data array using a single reusable CourseCard, then let the learner pick one.

It should
  • Keep the courses in one array of objects with title, lessons, and level.
  • Write one CourseCard component and use it for every course - no per-course components.
  • Each card shows the title, "N lessons", the level, and a Start Learning button.
  • Bonus: clicking Start Learning shows "You selected React" (or whichever course was chosen).
const courses = [ { title: 'React', lessons: 192, level: 'Beginner' }, { title: 'Node.js', lessons: 206, level: 'Intermediate' }, { title: 'Python', lessons: 75, level: 'Beginner' }, ]; function CourseCard(/* props */) { // title, "N lessons", level, and a Start Learning button } function CourseList() { // render one CourseCard per course }
Show one solution
import { useState } from 'react'; const courses = [ { title: 'React', lessons: 192, level: 'Beginner' }, { title: 'Node.js', lessons: 206, level: 'Intermediate' }, { title: 'Python', lessons: 75, level: 'Beginner' }, ]; function CourseCard({ title, lessons, level, onStart }) { return ( <article> <h2>{title}</h2> <p>{lessons} lessons</p> <p>{level}</p> <button onClick={() => onStart(title)}>Start Learning</button> </article> ); } function CourseList() { const [selected, setSelected] = useState(null); return ( <div> {courses.map((course) => ( <CourseCard key={course.title} title={course.title} lessons={course.lessons} level={course.level} onStart={setSelected} /> ))} {selected && <p>You selected {selected}</p>} </div> ); } export default CourseList; // One component, three courses. The data varies; the structure does not.

Key points

  • Keeping many parts of a page in sync by hand gets harder with every feature; React makes the page a function of the data instead.
  • Declarative UI replaces "which element do I change?" with "what should the screen look like now?".
  • One component, given different props, can render many different items.
  • Composing small components with one job each makes code easier to maintain, test, and debug.
  • React gives you components, props, state, declarative rendering, and composition - and nothing else.
  • Routing, server data, auth, and storage come from other tools.
  • React costs a toolchain and a learning curve, and guarantees neither speed nor good structure.
  • For a small, mostly static page, plain HTML, CSS, and JavaScript is the better choice.

Quick check before you move on

A learner completes a lesson and six parts of the page must change. What does React change about that work?
Instead of six hand-written updates, each part describes itself from the same data, so updating the data updates all six.
You have ReactCourseCard and NodeCourseCard that differ only in text. What should you do?
Merge them into one CourseCard and pass the differing text in as props.
Does React give you routing and a database?
No. React handles the UI; routing, server data, and storage come from other libraries and a backend.
Will moving an app to React make it faster?
Not by itself. Speed depends on how the app is designed - renders, bundle size, and network calls.

Interview questions

Why was React created?

To make complex, interactive UIs manageable. Instead of coordinating every DOM update by hand, you describe the UI from data with reusable components, and React keeps the page in step.

What is declarative programming?

Describing the result you want rather than the steps to produce it. In React, you describe what the UI should be for the current state.

What is imperative UI?

Controlling exactly how the UI changes, usually through direct DOM operations such as finding an element and setting its text.

What is component reusability?

Writing a UI component once and using it in many places with different data or configuration, passed in as props.

Does React eliminate DOM manipulation?

It removes most of it from your code, but React itself still updates the DOM - it works out the minimal changes and applies them for you.

What is a disadvantage of React?

It adds tooling and concepts - a build step, JSX, state, and a learning curve - that are unnecessary for small or mostly static sites. It also does not guarantee performance or good architecture on its own.

Quiz

  1. 1.

    Which programming style does React primarily encourage? A. Imperative B. Declarative C. Procedural SQL D. Assembly

  2. 2.

    Which approach directly tells the DOM what to change? A. Declarative B. Imperative C. Functional component D. JSX

  3. 3.

    What is a major advantage of React components? A. They automatically create databases B. They make UI pieces reusable C. They replace JavaScript D. They remove the need for CSS

  4. 4.

    Is <CourseCard /> a reusable React component? A. Yes B. No

  5. 5.

    Which statement is correct? A. React automatically provides a backend B. React automatically provides PostgreSQL C. React primarily focuses on UI D. React replaces HTTP APIs

  6. 6.

    Which is generally easier to maintain? A. One huge component containing the entire application B. Well-designed components with clear responsibilities

Comments

Sign in to leave a comment. Your name and photo come from Google; nothing else is shared.

Loading comments...