Imagine you are building something with LEGOs.
- Components are your individual LEGO bricks (
<Button />
,<Profile />
,<Header />
). - Props are the instructions you give to a brick.
- Hooks are special abilities you can give to a brick.
Part 1: Props (How Components Talk to Each Other)
The Core Idea: Props (short for "properties") are used to pass data from a parent component down to a child component. It's a one-way street: data only flows downwards.
The Analogy: Ordering at a Restaurant
- You (the Parent Component): You are the customer ordering a pizza.
- The Chef (the Child Component): The chef is the
<Pizza />
component. - Your Order (the Props): You tell the chef, "I want a large pizza with pepperoni and extra cheese." These specific instructions—
size: 'large'
,topping: 'pepperoni'
,extraCheese: true
—are the props.
The chef (<Pizza />
) receives these instructions and makes the pizza exactly as you ordered. The chef cannot change your order; they can only read it and act on it. This is the most important rule of props.
Key Characteristics of Props
- Read-Only: A child component can never change the props it receives. It can only use them.
- Data Flows Down: Data is passed from parent to child, to grandchild, and so on. A child cannot pass props "up" to its parent.
- They are Configuration: Props are how you configure and customize a reusable component.
Simple Code Example
Let's create a reusable WelcomeMessage
component.
// This is our "Chef" component. It's reusable.
// It expects to receive a `name` prop.
function WelcomeMessage({ name }) { // We "destructure" props to get the name directly
return (
<h1>Hello, {name}! Welcome to our app.</h1>
);
}
// This is our "Customer" or Parent component.
function App() {
return (
<div>
{/* We are using our WelcomeMessage component and giving it props */}
<WelcomeMessage name="Alice" />
<WelcomeMessage name="Bob" />
<WelcomeMessage name="Charlie" />
</div>
);
}
What's happening here?
- The
App
component is the parent. - It renders the
WelcomeMessage
component three times. - Each time, it passes a different
name
prop. - The
WelcomeMessage
component receives thatname
and displays it. We've created one reusable "template" and configured it differently each time using props.
Part 2: Hooks (Giving Components Memory and Superpowers)
The Core Idea: Before hooks, if you wanted a component to have its own internal "memory" (state) or do things when something happened (lifecycle events), you had to use cumbersome "Class Components." Hooks let you do all that and more in simple, clean "Functional Components."
Hooks are special functions that always start with the word use
(e.g., useState
, useEffect
).
Let's focus on the two most important hooks.
1. useState
(The Memory Hook)
The Analogy: A Personal Whiteboard
Imagine your component has a small whiteboard next to it.
- The
useState
hook gives your component this whiteboard. - The component can write something on the board (the initial state).
- It can look at what's on the board (the current state value).
- It gets a special magic marker that is the only way to update what's on the board (the setter function).
When the component uses its magic marker to update the whiteboard, React knows something has changed and automatically re-renders the component to show the new information.
Simple Code Example
Let's build a simple counter.
import React, { useState } from 'react';
function Counter() {
// 1. Give our component a "whiteboard" (state) called 'count'.
// The initial value is 0.
// We get back the current value (`count`) and the magic marker (`setCount`).
const [count, setCount] = useState(0);
return (
<div>
{/* 2. Display the current value from our whiteboard */}
<p>You clicked {count} times</p>
{/* 3. When this button is clicked, use the magic marker to update the board */}
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
What's happening here?
-
useState(0)
sets up the state. Thecount
variable starts at0
. - The component renders, showing "You clicked 0 times".
- When you click the button, the
onClick
function callssetCount(count + 1)
. - React sees that the state was updated. It re-runs the
Counter
function. - This time, the
count
variable is1
. - The component renders again, showing "You clicked 1 times".
2. useEffect
(The Action Hook)
The Analogy: "After ____ happens, do this."
useEffect
allows your component to perform "side effects"—actions that interact with the world outside of React. This includes things like:
- Fetching data from an API after the component first appears.
- Setting up a timer.
- Manually changing the document title.
It takes two arguments:
- A function to run (the "effect").
- An array of dependencies (the "trigger").
The dependency array tells useEffect
when to run the effect.
-
[]
(empty array): Run this effect only once, right after the component first renders on the screen. (Perfect for initial data fetching). -
[someVariable]
(array with variables): Run this effect every timesomeVariable
changes. - No array at all: Run after every single render. (This is usually a mistake and can cause infinite loops).
Simple Code Example
Let's log a message to the console when our Counter
component's count changes.
import React, { useState, useEffect } from 'react';
function CounterWithEffect() {
const [count, setCount] = useState(0);
// This is our "Action Hook"
useEffect(() => {
// This is the effect: log a message to the console.
console.log(`The new count is: ${count}`);
// This is the trigger: run the effect whenever `count` changes.
}, [count]);
// This effect runs only ONCE after the component first renders.
useEffect(() => {
console.log('Component has mounted!');
}, []);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
What's happening here?
- When the component first renders, the second
useEffect
runs, and you'll see "Component has mounted!" in the console. The firstuseEffect
also runs, printing "The new count is: 0". - When you click the button,
setCount
is called. - The state changes, so the component re-renders.
- Because
count
changed, the firstuseEffect
's trigger is activated, and it runs again, printing "The new count is: 1". The seconduseEffect
does not run again because its dependency array is empty.
Summary: Props vs. Hooks
Concept | Props | Hooks (useState , useEffect ) |
---|---|---|
Purpose | Pass data from Parent to Child | Give a component internal memory & actions |
Data Flow | Top-down (unidirectional) | Internal (manages its own data) |
Analogy | Configuration/Instructions (Ordering at a restaurant) | Memory/Abilities (A personal whiteboard) |
Can it be changed? | No. Read-only by the child. |
Yes. Changed via its setter function (e.g., setCount ). |
Example | <UserCard name="Bob" /> |
const [count, setCount] = useState(0); |
Props and Hooks work together. A parent component might fetch data using useEffect
, store it in its state using useState
, and then pass parts of that data down to child components as props.
Top comments (0)