React is packed with terminology that can sound intimidating at first—components, JSX, props, state, and hooks. But don't worry! In this two-part series, we'll break down every major React concept into simple, easy-to-understand explanations.
Part 1 (this post) covers the essential fundamentals you need to start building React apps.
Part 2 will dive into advanced patterns for building production-ready applications.
By the end of this post, you'll understand the core building blocks of React and be ready to create your first interactive components!
1. Components: The Building Blocks
What are they?
Components are the foundation of every React app. They're reusable pieces that represent visible parts of your UI—like buttons, inputs, forms, or entire pages.
Why are they useful?
Think of components like Lego blocks. Once you create one, you can use it as many times as you want throughout your app.
How do they work?
Every React component is simply a JavaScript function that returns markup:
function Button() {
return <button>Click Me!</button>;
}
You can use this Button component anywhere in your app, just like reusing a Lego piece!
2. JSX: JavaScript in Disguise
What is it?
JSX is a special syntax that looks like HTML but is actually JavaScript. It's what React components return to describe what should appear on the screen.
Why use it?
The alternative is using React.createElement() for everything, which gets tedious fast. JSX makes your code much more readable.
Key differences from HTML:
- Use
classNameinstead ofclass - Write attributes in camelCase (like
onClickinstead ofonclick) - You can embed JavaScript expressions using curly braces
{}
function Greeting() {
const name = "Sarah";
return <h1>Hello, {name}!</h1>; // Output: Hello, Sarah!
}
The One Parent Rule
Important: Components can only return one parent element. If you need multiple elements, wrap them in a parent <div> or use a React Fragment (<>...</>):
function App() {
return (
<>
<h1>Title</h1>
<p>Paragraph</p>
</>
);
}
Why use Fragments?
Sometimes you don't want to add an extra <div> to your DOM. Fragments let you group elements without creating unnecessary wrapper elements.
3. Props: Passing Data Between Components
What are they?
Props (short for "properties") are how you pass data from one component to another. Think of them as custom attributes you can add to your components.
How do they work?
// Passing a prop
<Welcome name="John" age={25} />
// Using the prop
function Welcome(props) {
return <h1>Hello, {props.name}! You are {props.age} years old.</h1>;
}
Modern syntax (destructuring):
function Welcome({ name, age }) {
return <h1>Hello, {name}! You are {age} years old.</h1>;
}
Can you pass anything as a prop?
Yes! Strings, numbers, arrays, objects, functions, and even other components.
The Special children Prop
When you put content between opening and closing component tags, it becomes accessible via the children prop:
<Card>
<h2>Title</h2>
<p>Content goes here</p>
</Card>
function Card({ children }) {
return (
<div className="card">
{children}
</div>
);
}
Why is this useful?
The children prop is perfect for creating layout components and practicing composition (organizing components in an optimal way). You can create reusable containers that work with any content!
Real-world example:
function Container({ children }) {
return (
<div className="max-width-container">
{children}
</div>
);
}
// Use it anywhere
<Container>
<Header />
<MainContent />
<Footer />
</Container>
4. The key Prop: Helping React Identify Components
What is it?
The key prop is a unique identifier React uses to tell components apart, especially when rendering lists.
When do you need it?
When creating lists with the .map() function:
const todos = [
{ id: 1, text: 'Learn React' },
{ id: 2, text: 'Build a project' },
{ id: 3, text: 'Deploy app' }
];
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
Why is it important?
Without keys, React might get confused about which items changed, leading to weird bugs or poor performance. React will warn you in the console if you forget them!
Best practices:
- ✅ Use unique IDs from your data:
key={item.id} - ⚠️ Use array index as last resort:
key={index}(okay for static lists) - ❌ Never use random values:
key={Math.random()}(breaks everything!)
5. Rendering: How React Displays Your UI
What is rendering?
Rendering is the process React uses to take your components and display them in the browser.
The Virtual DOM (VDOM)
React uses a clever optimization called the Virtual DOM:
- Your app's state changes (user clicks a button, data loads, etc.)
- React updates the Virtual DOM (a lightweight JavaScript copy of the real DOM)
- React uses diffing to compare the new Virtual DOM with the previous version
- React uses reconciliation to update only the changed parts of the real DOM
Why this matters:
This process makes React incredibly efficient. Instead of updating the entire page, React only updates what actually changed!
The DOM explained:
DOM stands for Document Object Model—it's how browsers represent all the HTML elements on a web page as a tree structure.
Warning: Infinite Re-renders!
Be careful not to update state during render. This creates an infinite loop and crashes your app:
// ❌ BAD - Infinite loop!
function BadComponent() {
const [count, setCount] = useState(0);
setCount(count + 1); // This runs on every render!
return <div>{count}</div>;
}
// ✅ GOOD - Update in event handler
function GoodComponent() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}
6. Event Handling: Responding to User Actions
What is it?
Event handling is how you detect and respond to user interactions like clicks, typing, and form submissions.
Common events:
-
onClick- User clicks an element -
onChange- Input value changes -
onSubmit- Form is submitted -
onMouseEnter- Mouse hovers over element -
onKeyDown- User presses a key
Example:
function AlertButton() {
const handleClick = () => {
alert('Button was clicked!');
};
return <button onClick={handleClick}>Click Me</button>;
}
Important: Notice we pass the function itself (handleClick), not handleClick()—we don't want to call it immediately!
Inline event handlers:
<button onClick={() => alert('Clicked!')}>
Click Me
</button>
Accessing event details:
function SearchInput() {
const handleChange = (event) => {
console.log('User typed:', event.target.value);
};
return <input onChange={handleChange} />;
}
7. State: Managing Dynamic Data
What is state?
State is like a snapshot of your app at any moment in time. It's data that can change based on user interaction or other events.
Why not use regular JavaScript variables?
Regular variables don't trigger React to re-render your UI. State does!
Using useState
How to use it:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // Start at 0
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
Breaking it down:
-
countis the current value (the state variable) -
setCountis the function to update it (the setter function) -
useState(0)sets the initial value to 0 - When
setCountis called, React re-renders the component with the new value
Multiple state variables:
function UserForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [age, setAge] = useState(0);
return (
<form>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<input value={age} onChange={(e) => setAge(e.target.value)} />
</form>
);
}
State with objects:
function UserForm() {
const [user, setUser] = useState({
name: '',
email: '',
age: 0
});
const updateName = (e) => {
setUser({ ...user, name: e.target.value }); // Spread to keep other fields
};
return <input value={user.name} onChange={updateName} />;
}
8. Controlled Components: Predictable Form Behavior
What are they?
Controlled components are form inputs whose values are controlled by React state. The state becomes the "single source of truth" for the input's value.
Example:
function NameForm() {
const [name, setName] = useState('');
return (
<div>
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
<p>You typed: {name}</p>
</div>
);
}
The flow:
- User types in the input
-
onChangefires and callssetNamewith the new value - State updates with the new value
- React re-renders
- Input displays the updated state value
Why use them?
Controlled components give you complete control over the input's value, making validation, formatting, and other logic much easier:
function EmailForm() {
const [email, setEmail] = useState('');
const handleChange = (e) => {
const value = e.target.value.toLowerCase(); // Force lowercase
setEmail(value);
};
return <input value={email} onChange={handleChange} />;
}
Complete form example:
function LoginForm() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = (e) => {
e.preventDefault(); // Prevent page refresh
console.log('Logging in:', { username, password });
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit">Login</button>
</form>
);
}
9. React Hooks: The Foundation
What are hooks?
Hooks are special functions that let you "hook into" React features like state and lifecycle methods within function components.
Rules of Hooks:
- Only call hooks at the top level (not inside loops, conditions, or nested functions)
- Only call hooks from React function components (not regular JavaScript functions)
The Most Common Hook: useState
We've already covered useState extensively—it's the hook you'll use most often for managing component state.
Other Important Hooks (Preview)
We'll cover these in detail in Part 2, but here's a quick overview:
useEffect - Perform side effects (API calls, subscriptions)
useEffect(() => {
// Run after render
}, [dependencies]);
useRef - Reference DOM elements or store mutable values
const inputRef = useRef(null);
useContext - Access data from React Context
const value = useContext(MyContext);
Don't worry about memorizing these now—we'll explore them thoroughly in the next post!
10. Pure Components: Predictable Behavior
What does "pure" mean?
A pure component is like a mathematical function—the same input (props) always produces the same output (JSX), with no side effects.
Pure component (✅ Good):
function Cup({ guest }) {
return <p>Tea cup for guest #{guest}</p>;
}
Impure component (❌ Avoid):
let guestCount = 0;
function Cup() {
guestCount = guestCount + 1; // Modifies external variable during render!
return <p>Tea cup for guest #{guestCount}</p>;
}
Why it matters:
React might render components multiple times for optimization. Impure components can produce unexpected results when rendered more than once:
// Using the impure Cup component
<>
<Cup /> {/* guestCount = 1 */}
<Cup /> {/* guestCount = 2 */}
<Cup /> {/* guestCount = 3 */}
</>
// But if React re-renders, counts will be wrong!
The fix (make it pure):
function Cup({ guest }) {
return <p>Tea cup for guest #{guest}</p>;
}
// Usage
<>
<Cup guest={1} />
<Cup guest={2} />
<Cup guest={3} />
</>
Strict Mode: Your Safety Net
What is it?
Strict Mode is a special component that helps catch common mistakes during development.
How to use it:
import { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>
);
What does it do?
- Highlights potential problems in your components
- Warns about unsafe lifecycle methods
- Detects unexpected side effects
- Warns about deprecated APIs
Important: Strict Mode only runs in development mode. It won't affect your production build!
Quick Reference: Core Concepts Checklist
Here's what we covered in Part 1:
✅ Components - Building blocks of React apps
✅ JSX - JavaScript syntax extension for writing UI
✅ Props - Passing data between components
✅ Key Prop - Helping React identify list items
✅ Rendering - How React displays your UI
✅ Event Handling - Responding to user actions
✅ State - Managing dynamic data with useState
✅ Controlled Components - Form inputs controlled by state
✅ Hooks - Functions for using React features
✅ Pure Components - Predictable, side-effect-free components
These fundamental concepts form the foundation of everything in React. Master them, and you'll find Part 2's advanced patterns much easier to understand!
Top comments (0)