React Complete Guide for Beginners
React is a powerful JavaScript library for building user interfaces, particularly web applications. Created by Facebook, React has become one of the most popular frontend frameworks in the world.
What is React?
React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called "components."
Key Features
- Component-Based: Build encapsulated components that manage their own state
- Virtual DOM: Efficient updates and rendering
- One-Way Data Flow: Predictable data flow makes debugging easier
- JSX: JavaScript syntax extension that looks like HTML
- Rich Ecosystem: Thousands of packages and tools available
Setting Up React
Using Create React App
The easiest way to get started with React is using Create React App:
npx create-react-app my-app
cd my-app
npm start
Using Vite (Recommended)
For faster development and better performance:
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
Components
Functional Components
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Using arrow function
const Welcome = (props) => {
return <h1>Hello, {props.name}!</h1>;
};
Class Components
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
JSX
JSX is a syntax extension that lets you write HTML-like code in JavaScript:
const element = <h1>Hello, world!</h1>;
// JSX with expressions
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
// JSX with attributes
const element = <div tabIndex="0"></div>;
const element = <img src={user.avatarUrl}></img>;
State and Props
Props
Props are read-only data passed down from parent components:
function UserCard(props) {
return (
<div className="user-card">
<h2>{props.name}</h2>
<p>{props.email}</p>
<span>Age: {props.age}</span>
</div>
);
}
// Usage
<UserCard name="John Doe" email="john@example.com" age={25} />
State with Hooks
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
React Hooks
useState Hook
import { useState } from 'react';
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log({ name, email });
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<button type="submit">Submit</button>
</form>
);
}
useEffect Hook
import { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
});
}, []); // Empty dependency array means this runs once
if (loading) return <div>Loading...</div>;
return <div>{JSON.stringify(data)}</div>;
}
Event Handling
function Button() {
const handleClick = (e) => {
e.preventDefault();
console.log('Button clicked!');
};
return (
<button onClick={handleClick}>
Click me
</button>
);
}
// With parameters
function TodoItem({ todo, onDelete }) {
return (
<div>
<span>{todo.text}</span>
<button onClick={() => onDelete(todo.id)}>
Delete
</button>
</div>
);
}
Conditional Rendering
function UserGreeting({ isLoggedIn, user }) {
if (isLoggedIn) {
return <h1>Welcome back, {user.name}!</h1>;
}
return <h1>Please sign up.</h1>;
}
// Using ternary operator
function LoginButton({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<button>Logout</button>
) : (
<button>Login</button>
)}
</div>
);
}
// Using logical AND
function Mailbox({ unreadMessages }) {
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 && (
<h2>You have {unreadMessages.length} unread messages.</h2>
)}
</div>
);
}
Lists and Keys
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
</li>
))}
</ul>
);
}
// More complex example
function ProductList({ products }) {
return (
<div className="product-grid">
{products.map(product => (
<div key={product.id} className="product-card">
<h3>{product.name}</h3>
<p>${product.price}</p>
<button>Add to Cart</button>
</div>
))}
</div>
);
}
Forms
import { useState } from 'react';
function ContactForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
message: ''
});
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('Form submitted:', formData);
// Handle form submission
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
placeholder="Your Name"
required
/>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="Your Email"
required
/>
<textarea
name="message"
value={formData.message}
onChange={handleChange}
placeholder="Your Message"
rows="5"
required
/>
<button type="submit">Send Message</button>
</form>
);
}
Best Practices
1. Component Structure
// Good: Single responsibility
function UserProfile({ user }) {
return (
<div className="user-profile">
<UserAvatar user={user} />
<UserInfo user={user} />
<UserActions user={user} />
</div>
);
}
// Bad: Too many responsibilities
function UserProfile({ user }) {
// Avatar, info, actions, settings, etc. all in one component
}
2. Props Destructuring
// Good
function UserCard({ name, email, avatar }) {
return (
<div>
<img src={avatar} alt={name} />
<h3>{name}</h3>
<p>{email}</p>
</div>
);
}
// Also good for many props
function UserCard(props) {
const { name, email, avatar, ...otherProps } = props;
return (
<div {...otherProps}>
<img src={avatar} alt={name} />
<h3>{name}</h3>
<p>{email}</p>
</div>
);
}
3. Custom Hooks
// Custom hook for API calls
function useApi(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
});
}, [url]);
return { data, loading, error };
}
// Usage
function UserList() {
const { data: users, loading, error } = useApi('/api/users');
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Next Steps
- Learn React Router: For client-side routing
- State Management: Redux, Zustand, or Context API
- Testing: Jest and React Testing Library
- Performance: React.memo, useMemo, useCallback
- Advanced Patterns: Higher-Order Components, Render Props
Resources
Happy coding with React!