Reimagining HTML for the Modern Web
One of the most compelling ways to think about React is to view it as the answer to a hypothetical question: "What would HTML look like if it were invented today?"
Traditionally, web development has been a tale of two worlds. On one side, you have HTML, which is loved for its declarative nature; you describe what you want (a heading, a list, an image), and the browser handles the rest. On the other side, you have JavaScript, a powerhouse language that offers tools to manage complexity — variables, scoping, modules, and functions.
React is essentially the "lovechild" of these two technologies. It offers the declarative syntax of HTML backed by the architectural power of JavaScript.
- •Why React combines HTML's declarative syntax with JavaScript's architectural power
- •How React solves the code repetition problem using components
- •The capitalization rule for components
- •How to organize components using the Single Responsibility Principle
- •The importance of component purity
But what does that actually look like in practice?
Let's explore how React brings together the best of both worlds through practical examples.
The "Copy-Paste" Problem
To understand why React is necessary, let's look at how we handled reuse in the old days. Imagine you are building an e-commerce site and you have the HTML for a single product card:
<article class="product-card">
<img src="/sneakers.jpg" alt="Cool Sneakers" />
<h3>Urban Runners</h3>
<p>$85.00</p>
<button>Add to Cart</button>
</article>This works perfectly for one item. But what if you have 12 products on a page? Or what if you want to reuse this exact card design on the "Checkout" page and the "Related Products" section?
Without a framework, the most common solution is the "CMD+C / CMD+V" method. You copy the code and paste it wherever you need it. This leads to a maintenance nightmare. If you decide to change the button text from "Add to Cart" to "Buy Now," you have to find and replace it in every single instance across your entire website.
The React Solution: Components
In JavaScript, we solved code repetition decades ago using functions. You wrap logic in a function, export it, and call it wherever you need it. React applies this exact same logic to HTML.
If we take our product card and "React-ify" it, it looks like this:
export default function ProductCard() {
return (
<article className="product-card">
<img src="/sneakers.jpg" alt="Cool Sneakers" />
<h3>Urban Runners</h3>
<p>$85.00</p>
<button>Add to Cart</button>
</article>
);
}If you have never seen React before, this might look strange. You are looking at HTML inside a JavaScript function. But this is the magic of React components. They are literally just functions that return a description of the UI.
The Capitalization Rule
You might notice a subtle but crucial detail: the function is named ProductCard, not productCard.
This is not a stylistic choice; it is a requirement.
- •Lowercase (e.g., <div>, <span>): React treats these as built-in DOM elements
- •Capitalized (e.g., <ProductCard />, <Navbar />): React treats these as custom components
Composition: Using Your Component
Now that we have encapsulated our HTML into a module, we can import it and use it anywhere. This is where the syntax gets interesting. We don't call the function like ProductCard(). Instead, we use it as if it were a custom HTML tag.
Here is how we might build a store page:
import ProductCard from './ProductCard';
export default function StorePage() {
return (
<main>
<h1>New Arrivals</h1>
<p>Check out our latest gear.</p>
<div className="grid">
<ProductCard />
<ProductCard />
<ProductCard />
</div>
</main>
);
}When this code runs, React effectively replaces every instance of <ProductCard /> with the HTML that the function returns. The final output the browser sees is exactly what you would expect: a main wrapper containing the header and three fully rendered product articles.
Organization and The Single Responsibility Principle
Once you realize that UI elements are just functions, the same rules of software engineering apply. A key principle is the Single Responsibility Principle (SRP): a component should ideally do one thing.
If you are building a complex dashboard, you might initially dump everything into one file:
import Sidebar from './Sidebar';
import Header from './Header';
import AnalyticsGraph from './AnalyticsGraph';
import UserList from './UserList';
import SettingsForm from './SettingsForm';
import Footer from './Footer';
export default function Dashboard() {
return (
<div className="layout">
<Sidebar />
<div className="content">
<Header />
<AnalyticsGraph />
<UserList />
<SettingsForm />
<Footer />
</div>
</div>
);
}This follows the SRP well — each part of the dashboard is its own component. However, creating a separate file for every tiny piece of UI can clutter your project directory.
A Rule of Thumb for Files
A good strategy for organizing components is:
- •Is it reused? If a component (like Button or ProductCard) is used in multiple places, put it in its own file
- •Is it specific? If a component is only used inside one specific page, you can define it inside that page's file
For example, if AnalyticsGraph and UserList are only ever used inside the Dashboard, you might refactor the file like this:
import Sidebar from './Sidebar';
import Header from './Header';
import Footer from './Footer';
// Sub-components defined in the same file because they aren't reused elsewhere
function AnalyticsGraph() {
return <div className="graph">...</div>;
}
function UserList() {
return <ul className="users">...</ul>;
}
export default function Dashboard() {
return (
<div className="layout">
<Sidebar />
<div className="content">
<Header />
<AnalyticsGraph />
<UserList />
<Footer />
</div>
</div>
);
}The Golden Rule: Purity
Finally, there is one critical concept to embrace: Purity.
In computer science, a "pure function" is one that always returns the same output given the same input and has no side effects (like changing global variables). React relies heavily on this concept.
Your components should just be blueprints. If you render <ProductCard /> ten times, it should look the same way ten times. By keeping your components pure, you ensure that your application is predictable and easy to debug.
If you need to handle "side effects"—like fetching data from a server or changing the document title—React has specific ways to handle those (which we call hooks), but the rendering logic itself should remain pure.