React is a JavaScript library for building user interfaces. Created by Facebook, it's the most popular choice for modern web development, used by companies like Netflix, Airbnb, and Instagram.
Why React?
React has become the go-to choice for frontend development because:
- Component-based: Build encapsulated, reusable UI pieces
- Declarative: Describe what you want, React handles the DOM updates
- Virtual DOM: Efficient updates for better performance
- Huge ecosystem: Thousands of libraries, tools, and resources
- Strong job market: Most in-demand frontend skill
React vs Vanilla JavaScript
// Vanilla JavaScript - imperative
const button = document.createElement('button');
button.textContent = 'Clicks: 0';
let count = 0;
button.addEventListener('click', () => {
count++;
button.textContent = 'Clicks: ' + count;
});
document.body.appendChild(button);
// React - declarative
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicks: {count}
</button>
);
} Getting Started
The easiest way to start a new React project is with Vite or Create React App:
# Using Vite (recommended)
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev
# Using Create React App
npx create-react-app my-app
cd my-app
npm start Project Structure
my-app/
├── src/
│ ├── App.jsx # Main component
│ ├── main.jsx # Entry point
│ ├── index.css # Global styles
│ └── components/ # Your components
├── public/ # Static assets
├── package.json # Dependencies
└── vite.config.js # Build configuration Components
Components are the building blocks of React applications. They're JavaScript functions that return JSX (HTML-like syntax in JavaScript).
Function Components
// Simple component
function Welcome() {
return <h1>Hello, World!</h1>;
}
// Component with JSX expressions
function Greeting() {
const name = "Alice";
const date = new Date().toLocaleDateString();
return (
<div>
<h1>Hello, {name}!</h1>
<p>Today is {date}</p>
</div>
);
}
// Using the component
function App() {
return (
<div>
<Welcome />
<Greeting />
</div>
);
} JSX Rules
- Single root element: Wrap multiple elements in a
<div>or<>...</> - Close all tags: Including self-closing tags like
<img /> - camelCase attributes:
classNameinstead ofclass,onClickinstead ofonclick - JavaScript in curly braces:
{expression}
Props & State
Props pass data from parent to child. State manages data that changes over time.
Props (Properties)
// Parent passes props
function App() {
return <UserCard name="Alice" role="Developer" />;
}
// Child receives props
function UserCard({ name, role }) {
return (
<div className="card">
<h2>{name}</h2>
<p>{role}</p>
</div>
);
}
// Props with default values
function Button({ text = "Click me", variant = "primary" }) {
return <button className={variant}>{text}</button>;
} State with useState
import { useState } from 'react';
function Counter() {
// Declare state variable with initial value
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<button onClick={() => setCount(0)}>
Reset
</button>
</div>
);
} State with Objects
function Form() {
const [user, setUser] = useState({
name: '',
email: ''
});
const handleChange = (e) => {
setUser({
...user, // Keep existing values
[e.target.name]: e.target.value // Update changed field
});
};
return (
<form>
<input
name="name"
value={user.name}
onChange={handleChange}
placeholder="Name"
/>
<input
name="email"
value={user.email}
onChange={handleChange}
placeholder="Email"
/>
</form>
);
} Hooks
Hooks let you use state and other React features in function components.
useEffect - Side Effects
import { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Runs after component mounts
fetch('https://api.example.com/data')
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
});
}, []); // Empty array = run once on mount
if (loading) return <p>Loading...</p>;
return <pre>{JSON.stringify(data, null, 2)}</pre>;
} Common Hooks
| Hook | Purpose |
|---|---|
useState | Manage component state |
useEffect | Side effects (data fetching, subscriptions) |
useContext | Access context values |
useRef | Reference DOM elements or persist values |
useMemo | Memoize expensive calculations |
useCallback | Memoize functions |
Event Handling
function EventExamples() {
const handleClick = () => {
alert('Button clicked!');
};
const handleSubmit = (e) => {
e.preventDefault(); // Prevent form submission
console.log('Form submitted');
};
const handleInput = (e) => {
console.log('Input value:', e.target.value);
};
return (
<div>
<button onClick={handleClick}>Click Me</button>
<form onSubmit={handleSubmit}>
<input onChange={handleInput} />
<button type="submit">Submit</button>
</form>
</div>
);
} Conditional Rendering
function Dashboard({ isLoggedIn, isAdmin }) {
// Using ternary operator
return (
<div>
{isLoggedIn ? (
<h1>Welcome back!</h1>
) : (
<h1>Please log in</h1>
)}
{/* Using && for conditional display */}
{isAdmin && <button>Admin Panel</button>}
</div>
);
}
// Early return pattern
function UserProfile({ user }) {
if (!user) {
return <p>No user found</p>;
}
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
} Lists & Keys
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: 'Learn React', done: false },
{ id: 2, text: 'Build a project', done: false },
{ id: 3, text: 'Deploy to production', done: false }
]);
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, done: !todo.done } : todo
));
};
return (
<ul>
{todos.map(todo => (
<li
key={todo.id} // Always use unique keys!
onClick={() => toggleTodo(todo.id)}
style={{ textDecoration: todo.done ? 'line-through' : 'none' }}
>
{todo.text}
</li>
))}
</ul>
);
} Why Keys? Keys help React identify which items changed, were added, or removed.
Always use stable, unique identifiers (like IDs), not array indices.
Next Steps
You've learned the React fundamentals! Continue your journey:
- React Router: Add navigation and multiple pages
- State management: Redux, Zustand, or Context API for complex state
- Styling: CSS Modules, Tailwind CSS, or styled-components
- Next.js: Full-stack React framework with SSR
- Testing: Jest and React Testing Library