Environment, Components & Thinking in React
Environment, Components & Thinking in React
Why React? The DOM Mutation Problem
Imagine building a dashboard: a user menu, a data table, a notification badge, and a sidebar. When a user logs in, every element that displays user data needs to update. In vanilla JavaScript that means:
document.querySelector('#nav-username').textContent = user.name
document.querySelector('#avatar').src = user.avatar
document.querySelector('#badge').textContent = notifications.length
document.querySelector('#sidebar-name').textContent = user.name
// ... one line per DOM node, foreverThis is imperative UI — you manually describe every mutation. As the app scales, this becomes unmanageable. Miss one update and the UI is inconsistent. Add a new feature and you must trace every element it affects.
React introduces a declarative model: instead of saying "update element X", you say "given this state, the UI looks like this." React computes the minimum DOM changes needed. This is the mental shift that makes React transformative — you focus on what the UI should look like, not how to get there.
Setting Up Your Environment
Create React App is officially deprecated. The modern standard is Vite.
Step 1 — Create the project:
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run devYour app is live at http://localhost:5173. Vite uses native ES modules so hot module replacement (HMR) is near-instant — save a file and the browser updates in milliseconds without reloading.
Step 2 — VS Code extensions to install:
Open VS Code and install these extensions:
- ES7+ React/Redux/React-Native snippets (by dsznajder): Type
rafceand press Tab to scaffold a complete arrow-function component. Saves minutes every day. - Prettier - Code Formatter: Set to "Format on Save" for consistent style across your project.
Step 3 — React Developer Tools (browser extension):
Install from the Chrome or Firefox extension store. It adds a Components tab to DevTools. You can inspect the component tree, view props and state in real time, and see exactly why each component re-renders — essential for debugging.
Your Project File Structure
After npm create vite, you get:
my-app/
src/
main.jsx ← entry point — mounts <App /> into index.html
App.jsx ← root component rendered into the DOM
assets/ ← images, SVGs, static files
components/ ← create this folder for your own components
Card.jsx
Button.jsx
NavBar.jsx
index.html ← single HTML page — Vite injects your bundle here
vite.config.js ← build configuration
package.jsonEvery component lives in a .jsx (or .tsx for TypeScript) file. Components export as named or default exports and import into parent components.
What Is a Component?
A component is a JavaScript function that:
- Accepts one argument — an object called props (or no argument if it takes no input)
- Returns JSX — a description of the UI to render
// src/components/Card.jsx
export function Card({ title, description, imageUrl }) {
return (
<div className="card">
<img src={imageUrl} alt={title} />
<h2>{title}</h2>
<p>{description}</p>
</div>
)
}When React encounters <Card title="React" /> it calls this function, receives JSX, and renders it to the DOM. When props change, React calls the function again, diffs the new JSX against the previous output, and surgically updates only the changed DOM nodes.
JSX Is Not HTML — Three Critical Differences
1. Use `className` not `class`:
// Wrong — class is a reserved keyword in JavaScript
<div class="container">
// Correct
<div className="container">2. Event handlers are camelCase and receive function references, not strings:
// HTML — lowercase, string handler
<button onclick="handleClick()">
// JSX — camelCase, pass the function directly
<button onClick={handleClick}>
<input onChange={handleChange} onKeyDown={handleKeyDown} />3. All tags must be explicitly closed:
// Wrong — implicit closing not allowed
<img src="/logo.png">
<input type="text">
<br>
// Correct — self-closing syntax required
<img src="/logo.png" alt="Logo" />
<input type="text" />
<br />Component Composition — The Real Power of React
Simple components compose into complex UIs by nesting. Props flow down the tree from parent to child:
// src/components/Button.jsx
export function Button({ children, variant = 'primary', onClick }) {
return (
<button className={`btn btn-${variant}`} onClick={onClick}>
{children}
</button>
)
}
// src/App.jsx
import { Card } from './components/Card'
import { Button } from './components/Button'
export default function App() {
return (
<main className="app">
<Card
title="React Crash Course"
description="Build interactive UIs with hooks and components."
imageUrl="/courses/react.jpg"
/>
<Button variant="primary" onClick={() => alert('Enrolled!')}>
Enroll Now
</Button>
</main>
)
}The children prop is special — it receives whatever is nested between a component's opening and closing tags. In <Button>Enroll Now</Button>, the string "Enroll Now" becomes props.children. This is how all layout wrapper components work in React.
Importing Between Files
// Named export — import with curly braces
export function Card({ ... }) { ... }
import { Card } from './components/Card'
// Default export — import without curly braces
export default function App() { ... }
import App from './App'Convention: one component per file. The file name matches the component name. This makes codebases easy to navigate.