States and Props are essential concepts for managing data and rendering components dynamically
In React, State is a local, mutable object used to manage dynamic data within a component, updated using useState
or setState
. Props, on the other hand, are immutable properties passed from a parent component to a child to make components reusable and dynamic. While state manages internal data, props handle data communication between components.
In React, useState is a Hook that allows you to manage the state of a functional component. State is essentially data that can change over time and affect what gets rendered on the screen. useState returns an array containing two values: the current state and a function to update that state.
Props (short for properties) allow you to pass data from one component to another, typically from a parent component to a child component. Props are read-only and cannot be modified within the child component, making them a way to pass information down the component tree.
Example 1: Managing State with useState
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
Explanation
Output
After clicking the button, the count will increase by 1.
Passing Data via Props
import React from 'react';
// Child component
function DisplayMessage({ message }) {
return <h2>{message}</h2>;
}
// Parent component
function App() {
const myMessage = "Hello from the parent component!";
return (
<div>
<DisplayMessage message={myMessage} />
</div>
);
}
export default App;
Explanation
Output
Understanding State Immutability
State immutability means that the state should not be directly modified. Instead, a new state object or array should be created whenever the state is updated. This ensures that React can properly detect changes and re-render components efficiently.
Directly mutating the state can lead to unexpected behavior and bugs. This is because React relies on detecting differences between previous and current states (called "shallow comparison").
Example 2: Incorrect and Correct State Updates
Incorrect State Update (Direct Mutation)
import React, { useState } from 'react';
function IncorrectArrayUpdate() {
const [items, setItems] = useState([1, 2, 3]);
const addItem = () => {
items.push(4); // Direct mutation (incorrect)
setItems(items); // React might not re-render properly
};
return (
<div>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
<button onClick={addItem}>Add Item</button>
</div>
);
}
export default IncorrectArrayUpdate;
Explanation
Here, we are directly mutating the array items using items.push(4). React may not properly re-render the component because it doesn't detect that the state has changed.
Correct State Update (Immutability Preserved)
import React, { useState } from 'react';
function CorrectArrayUpdate() {
const [items, setItems] = useState([1, 2, 3]);
const addItem = () => {
// Create a new array with the existing items and the new item
setItems([...items, 4]);
};
return (
<div>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
<button onClick={addItem}>Add Item</button>
</div>
);
}
export default CorrectArrayUpdate;
Explanation
Output
Before clicking "Add Item":
After clicking "Add Item":
Summary
___________________________________________________________________
Concept: Managing state with useState to add items to a cart, update item quantities, and display the total price.
Goal: Create a basic shopping cart app where users can add items, update quantities, and view the total price.
Components:
App: Main component that holds the state for cart items.
ProductList: Displays the list of products.
ProductItem: Represents a single product with an "Add to Cart" button.
Cart: Displays the added items, quantities, and total price.
App.jsx
import React, { useState } from 'react';
import ProductList from './ProductList';
import Cart from './Cart';
import './App.css';
const App = () => {
const [cart, setCart] = useState([]);
const addToCart = (product) => {
const productExists = cart.find(item => item.id === product.id);
if (productExists) {
setCart(cart.map(item =>
item.id === product.id
? { ...productExists, quantity: productExists.quantity + 1 }
: item
));
} else {
setCart([...cart, { ...product, quantity: 1 }]);
}
};
const updateQuantity = (productId, quantity) => {
setCart(cart.map(item =>
item.id === productId ? { ...item, quantity } : item
));
};
return (
<div className="app">
<h1>Shopping Cart App</h1>
<ProductList addToCart={addToCart} />
<Cart cart={cart} updateQuantity={updateQuantity} />
</div>
);
};
export default App;
ProductList.jsx
import React from 'react';
import ProductItem from './ProductItem';
const products = [
{ id: 1, name: 'Laptop', price: 1000 },
{ id: 2, name: 'Phone', price: 500 },
];
const ProductList = ({ addToCart }) => {
return (
<div className="product-list">
{products.map(product => (
<ProductItem key={product.id} product={product} addToCart={addToCart} />
))}
</div>
);
};
export default ProductList;
ProductItem.jsx
import React from 'react';
const ProductItem = ({ product, addToCart }) => {
return (
<div className="product-item">
<h3>{product.name}</h3>
<p>Price: ${product.price}</p>
<button onClick={() => addToCart(product)}>Add to Cart</button>
</div>
);
};
export default ProductItem;
Cart.jsx
import React from 'react';
const Cart = ({ cart, updateQuantity }) => {
const total = cart.reduce((acc, item) => acc + item.price * item.quantity, 0);
return (
<div className="cart">
<h2>Cart</h2>
{cart.map(item => (
<div key={item.id} className="cart-item">
<span>{item.name}</span>
<span>
Quantity:
<input
type="number"
value={item.quantity}
onChange={(e) => updateQuantity(item.id, Number(e.target.value))}
/>
</span>
<span>Price: ${item.price * item.quantity}</span>
</div>
))}
<h3>Total: ${total}</h3>
</div>
);
};
export default Cart;
App.css
.app {
padding: 20px;
text-align: center;
}
.product-list {
display: flex;
justify-content: space-around;
}
.product-item {
border: 1px solid #ccc;
padding: 20px;
border-radius: 5px;
margin: 10px;
}
.cart {
margin-top: 20px;
}
.cart-item {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
How We Use States and Props Here:
State:
We use useState in the App component to manage the cart (cart state), which stores the items added by the user.
The state also keeps track of the quantity of each item.
setCart is used to update the cart state whenever a new item is added, quantity is changed, or an item is removed.
Props:
The addToCart function is passed as a prop from App to ProductList and then to each ProductItem.
The cart and updateQuantity functions are passed as props to the Cart component to display the items and update their quantities.
_______________________________________________________________
1. What does the useState hook in React return?
A. An array with a single value.
B. A tuple with a value and a function to update the value.
C. An object with key-value pairs.
D. A promise.
Answer: B
Explanation: useState returns a tuple containing the current state and a function to update that state.
2. What is the correct syntax to use useState in a functional component?
A. const [state, setState] = useState(initialValue)
B. const state = useState(initialValue)
C. useState(state, setState)
D. const [state] = useState(initialValue)
Answer: A
Explanation: useState should be used as const [state, setState] to declare the state variable and the function to update it.
3. Which of the following is NOT a valid initial value for useState?
A. undefined
B. null
C. false
D. this
Answer: D
Explanation: this is not used in functional components. useState can take any JavaScript value as an initial state.
4. How do you update the state value in React using useState?
A. Directly modify the state variable.
B. Call the setter function returned by useState.
C. Use setState method like in class components.
D. Use the forceUpdate method.
Answer: B
Explanation: In functional components, the setter function (like setState) is used to update the state.
5. What happens if you directly modify a state variable instead of using its setter function?
A. The UI will still update.
B. The change will be ignored.
C. React will throw an error.
D. The state will be updated but the component won't re-render.
Answer: D