Advantages of spread operator
Adding New Properties
Merging Multiple Objects
Overwriting/Updating Existing Properties
How to Merge All Data into One Object
How to updates states using prev keyword in React
Updating React state while filtering using prev keyword in React
Dynamic Merge Example
Adding new properties on even click
Advantages of spread operator
Easy Copying and Updating
Allows you to clone objects and arrays without affecting the original data.
You can quickly replace, add, or remove properties in a new copy instead of mutating the source.
Immutability
Keeps data immutable—an essential practice in React for predictable UI updates.
Prevents bugs that occur from accidental data mutations.
Readable and Concise Code
Makes updates and mergers clear, concise, and easy to maintain.
Multiple Property Overwrites
Lets you apply many changes at once, all in one line.
Adding New Properties
const booking = { id: 12, status: "pending" };
// Add a new property 'vendor'
const withVendor = {
...booking,
vendor: "Royal Cars", // added
};
// Result: { id: 12, status: "pending", vendor: "Royal Cars" }
You get a new object with the all previous properties plus the new one added.
Merging Multiple Objects
const booking = { id: 12, status: "pending" };
const details = { price: 2000, start_date: "2025-10-01" };
// Merge everything
const merged = {
...booking,
...details,
};
// Result: { id: 12, status: "pending", price: 2000, start_date: "2025-10-01" }
All properties from both objects are combined into one new object.
Overwriting/Updating Existing Properties
const booking = { id: 12, status: "pending", price: 2000 };
// Overwrite price and status
const updated = {
...booking,
status: "confirmed", // overwritten
price: 2500, // overwritten
};
// Result: { id: 12, status: "confirmed", price: 2500 }
Common Usage Scenarios
React State Updates
Used in setState or hooks (useState) to update part of the state without mutating it.
setBooking(prev => ({ ...prev, status: "confirmed", price: 2500 }))
Merging Configuration Objects
Combine defaults with overrides:
const config = { ...defaultConfig, ...userConfig };
Copying and Extending Data
For arrays and objects, when you want a new copy with some updates.
const newArray = [...oldArray, newItem];
const newObj = { ...oldObj, newKey: newValue };
How to Merge All Data into One Object
Step 1: Existing Booking Object
const booking = {
id: 251,
user_id: 32,
status: "pending",
price: 12000,
start_date: "2025-10-05",
end_date: "2025-10-10"
};
Step 2: Dynamic Data from the Backend
Suppose these responses come in from an API call:
const userProfile = {
name: "Vijay Kumar",
email: "vijay@example.com",
phone: "+91-9998887777",
loyalty_points: 240
};
const shopInfo = {
shop_id: 11,
shop_name: "Royal Cars",
location: "Connaught Place, Delhi"
};
const vehicleDetails = {
vehicle_id: 303,
make: "Toyota",
model: "Fortuner",
year: 2024,
color: "White"
};
const bookingComments = {
comments: [
"Great service!",
"Delayed pick-up but resolved quickly."
]
};
Step 3: Merge All Data into One Object
With the spread operator, you create a single enriched object:
const enrichedBooking = {
...booking, // basic booking info
...userProfile, // user profile details
...shopInfo, // shop details
...vehicleDetails, // vehicle details
...bookingComments, // any comments list
booking_source: "Web Admin", // add new static/custom field
status: "confirmed" // overwrite status to 'confirmed'
};
Resulting Object/output
{
id: 251,
user_id: 32,
status: "confirmed", // overwritten
price: 12000,
start_date: "2025-10-05",
end_date: "2025-10-10",
name: "Vijay Kumar",
email: "vijay@example.com",
phone: "+91-9998887777",
loyalty_points: 240,
shop_id: 11,
shop_name: "Royal Cars",
location: "Connaught Place, Delhi",
vehicle_id: 303,
make: "Toyota",
model: "Fortuner",
year: 2024,
color: "White",
comments: [
"Great service!",
"Delayed pick-up but resolved quickly."
],
booking_source: "Web Admin"
}
How to updates states using prev keyword in React
prev is a javascript keyword
Some Other Common Variable Names Used Like prev:
When using the functional updater with useState or setState, here are some common parameter names developers use:
prev or prevState
previous or previousState
current
oldValue, old, value
state (often used in React class components)
For counters or similar situations:
prevCount, count
prevAge, age
etc.
Example with different names:
setCount(current => current + 1)
setAge(prevAge => prevAge + 1)
setBooking(previousBooking => ({ ...previousBooking, status: "confirmed" }))
setState((state, props) => ({ counter: state.counter + props.increment }))
Key Point
The name is not special; React will pass the current state value as the argument, and you pick the name for clarity.
Why Use prev?
State updates in React can be asynchronous; using the functional form guarantees you work with the most up-to-date previous state.
When you need to base new state on the old (like incrementing, toggling, merging objects), you use the functional updater: setState(prev => ...).
import React, { useState } from "react";
function BookingCard() {
// Initial state object
const [booking, setBooking] = useState({
id: 1,
status: "pending",
price: 2000,
date: "2025-10-09"
});
// Handler to update status and price, using prev
const updateBooking = () => {
setBooking(prev =>
({
...prev, // copies all properties from previous state
status: "confirmed", // overwrites status
price: 2500 // overwrites price
})
);
};
// Handler to simulate incrementing price safely with prev
const incrementPrice = () => {
setBooking(prev =>
({
...prev,
price: prev.price + 100 // always based on the latest price
})
);
};
return (
<div style={{ maxWidth: 400, margin: "30px auto", border: "1px solid #ccc", borderRadius: 8, padding: 20 }}>
<h2>Booking Details</h2>
<p><strong>ID:</strong> {booking.id}</p>
<p><strong>Status:</strong> {booking.status}</p>
<p><strong>Price:</strong> ₹{booking.price}</p>
<p><strong>Date:</strong> {booking.date}</p>
<button
style={{ marginTop: 20, padding: "10px 24px", borderRadius: 6, background: "#2098d1", color: "#fff", border: "none" }}
onClick={updateBooking}
>
Confirm & Set Price ₹2500
</button>
<button
style={{ marginLeft:10, marginTop: 20, padding: "10px 24px", borderRadius: 6, background: "#fbc531", color: "#222", border: "none" }}
onClick={incrementPrice}
>
Increment Price +₹100
</button>
</div>
);
}
export default BookingCard;
Explanation of prev
In setBooking(prev => { ... }), prev refers to the most recent state—important in async scenarios, batching, or event-driven updates.
The spread operator ...prev copies all previous fields, then fields you specify after the comma overwrite/add values.
For multiple rapid updates (say, clicks or events), using prev ensures you never work with a stale value.
Summary:
The "prev" style ensures React gets your updates right, even in complex/async render cycles.
Use it for merges, property updates, counters, or any state change that depends on the last value.
Updating React state while filtering using prev keyword in React
*my code is *
<div className="searchcontainer">
{/* Show Toggle Button in Mobile View */}
{isMobile && (
<button
className="toggle-btn"
onClick={() => setIsFilterOpen(!isFilterOpen)}
>
{isFilterOpen ? "Hide Filters ▲" : "Show Filters ▼"}
</button>
)}
{/* Sidebar Filter Section */}
<div
className={`filtersection ${
isMobile && !isFilterOpen ? "closed" : "open"
}`}
// style={{ width: "100%" }}
>
<h2>Filter Vehicles</h2>
<div className="filter-group">
<label>Price Range:</label>
<input
type="range"
name="priceRange"
min="0"
max="9999"
value={filters.priceRange}
onChange={handleFilterChange}
/>
<span className="price-value">{filters.priceRange} ₹</span>
</div>
<div className="form-row">
<div className="col-6">
<select
name="paymode"
value={formData.paymode}
onChange={handleChange}
required
>
<option value="8">Select All</option>
<option value="1">pay at online</option>
<option value="2">Pay at picked up</option>
</select>
</div>
</div>
<div className="form-row">
<div className="col-6">
<select
name="vehicleType"
value={formData.vehicleType}
onChange={handleChange}
required
>
<option value="" disabled>
Select Vehicle Type
</option>
<option value="car">Car</option>
<option value="bike">Bike</option>
<option value="bicycle">Bicycle</option>
</select>
</div>
</div>
<div className="form-row">
<div className="col-6">
<select
name="brand"
value={formData.brand}
onChange={handleChange}
required
disabled={!filteredBrands.length}
>
<option value="" >
Select Brand
</option>
{filteredBrands.map((brand, index) => (
<option key={index} value={brand}>
{brand}
</option>
))}
</select>
</div>
</div>
<div className="form-row">
<div className="col-6">
<select
name="model"
value={formData.model}
onChange={handleChange}
required
disabled={!filteredBrands.length}
>
<option value="" >
Select Model
</option>
{filteredModels.map((model, index) => (
<option key={index} value={model}>
{model}
</option>
))}
</select>
</div>
</div>
{/* Date Filters */}
<div className="filter-row">
<div className="filter-item">
<DatePicker
selected={parseLocalDate(filters.startDate)}
onChange={date => {
const value = date ? formatDateToYYYYMMDD(date) : "";
handleFilterChange({
target: { name: "startDate", value }
});
}}
minDate={new Date()} // Disable past dates
placeholderText="Select start date"
dateFormat="dd-MM-yyyy"
className="custom-datepicker-input"
/>
</div>
<br />
<div className="filter-item">
<DatePicker
selected={parseLocalDate(filters.endDate)}
onChange={date => {
const value = date ? formatDateToYYYYMMDD(date) : "";
handleFilterChange({
target: { name: "endDate", value }
});
}}
minDate={
filters.startDate
? parseLocalDate(filters.startDate)
: new Date() // Today if no start date
}
placeholderText="Select end date"
dateFormat="dd-MM-yyyy"
className="custom-datepicker-input"
/>
</div>
</div>
<div className="filter-item">
<label>Location:</label>
{locationOptions.length > 0 ? (
<Select
options={locationOptions}
value={
locationOptions.find(
(option) => option.value === filters.location
) || null
}
onChange={handleLocationChange}
placeholder="Search city..."
isSearchable
/>
) : (
<div style={{ color: "#888", fontStyle: "italic" }}>Loading cities...</div>
)}
</div>
Why Use Functional Update (prev) in React?
React state updates may be asynchronous or batched.
If multiple updates happen quickly, a direct update (setState(newState)) may use a stale value.
Functional update syntax—setState(prev => ...)—always uses the latest resolved state.
handleFilterChange Function
const handleFilterChange = (e) => {
setIsLoading(true);
setbikeFilterOpen(true);
const { name, value } = e.target;
setFilters((prev) => {
const updatedFilters = { ...prev, [name]: value };
if (
name === "startDate" &&
updatedFilters.endDate &&
new Date(value) > new Date(updatedFilters.endDate)
) {
updatedFilters.endDate = "";
}
return updatedFilters;
});
};
Your handleChange Function
const handleChange = (e) => {
setIsLoading(true);
setbikeFilterOpen(true);
const { name, value } = e.target;
setFormData((prevData) => ({
...prevData,
[name]: value,
}));
if (name === "vehicleType") {
filterBrands(value);
setFormData({ vehicleType: value, brand: "", model: "" }); // Reset
setFilteredModels([]);
setFilters((prev) => ({
...prev,
vehicleType: value,
brand: "",
model: "",
}));
}
if (name === "brand") {
filterModels(value);
setFormData((prevData) => ({ ...prevData, model: "" }));
setFilters((prev) => ({ ...prev, brand: value }));
}
if (name === "model") {
setFilters((prev) => ({ ...prev, model: value }));
}
if (name === "paymode") {
setFormData((prevData) => ({ ...prevData, paymode: value }));
setFilters((prev) => ({ ...prev, paymode: value }));
}
};
Dynamic Merge Example
Original Object
const booking = {
id: 251,
status: "pending",
price: 12000,
start_date: "2025-10-05"
};
const enrichedBooking = {
...booking, // copies all fields from booking
price: 12500, // **overwrites** (was 12000, now 12500)
shop_name: "Royal Cars", // **adds** new property
comments: ["Service was great!"], // **adds** new property
status: "confirmed", // **replaces** (was "pending", now "confirmed")
color: "White" // **adds** new property
};
output
{
id: 251,
status: "confirmed", // replaced
price: 12500, // overwritten
start_date: "2025-10-05",
shop_name: "Royal Cars", // added
comments: ["Service was great!"], // added
color: "White" // added
}
Adding new properties on event click
Given Data
[
{
"id": 34,
"vendor_id": "3002",
"user_id": "3321",
"shop_id": "8126",
"vehicle_id": "23305",
"vehicle_type_id": "91",
"notification_type": "booking_auto_cancelled_paid",
"booking_id": "915",
"payment_id": "216",
"content": "Booking 915 has been auto-cancelled after payment timeout. Vehicle: BMW C 400 GT. User: Abhishek Singh.",
"status": "sent",
"delivery_channel": "system",
"created_at": "2025-09-05T16:00:02.000000Z",
"updated_at": "2025-09-05T16:00:02.000000Z",
"user": {
"id": 3321,
"name": "Abhishek Singh",
"email": "abhisheksingh0860@gmail.com",
"email_verified_at": "2025-08-25T07:27:50.000000Z",
"number_verified_at": "2025-08-25 07:27:50",
"role": "user",
"number": 917079488615,
"address": "Bokaro Steel City, Jharkhand, India",
"main_location": null,
"state": "Jharkhand",
"city": "Bokaro Steel City",
"state_id": null,
"city_id": null,
"driving_lic": null,
"qrcode": null,
"profile_img": "profile_image_202509051051.jpg",
"adhar": "73834949",
"pinCode": "831020",
"company_details": null,
"status": "active",
"token": null,
"sms_notification": "1",
"email_notification": "1",
"whatsapp_notification": "1",
"created_at": "2025-08-13T13:05:33.000000Z",
"updated_at": "2025-09-05T10:51:38.000000Z"
},
"vendor": {
"id": 3002,
"name": "Rakesh kumar",
"email": "rakeshdev.cotocus@gmail.com",
"email_verified_at": "2025-08-25T10:49:19.000000Z",
"number_verified_at": "2025-08-25 10:49:19",
"role": "user",
"number": 917488127637,
"address": null,
"main_location": null,
"state": null,
"city": null,
"state_id": null,
"city_id": null,
"driving_lic": null,
"qrcode": null,
"profile_img": null,
"adhar": null,
"pinCode": null,
"company_details": null,
"status": "active",
"token": null,
"sms_notification": "1",
"email_notification": "1",
"whatsapp_notification": "1",
"created_at": "2025-08-21T05:32:29.000000Z",
"updated_at": "2025-08-25T10:49:19.000000Z"
},
"vehicle": {
"id": 23305,
"vender_ID": 3002,
"shop_id": "8126",
"vehical_id": "91",
"imei": null,
"vechicle": "bike",
"shoplocation": "Bokaro Steel City, Jharkhand, India",
"brand": "BMW",
"model": "C 400 GT",
"price": "3434",
"address": null,
"state": null,
"city": null,
"number": "KA05HC2483",
"vendor_email": "rakeshdev.cotocus@gmail.com",
"numbers_of_vechile": "KA05HC2483",
"Bookings": 1,
"available_vehicle": null,
"rc_number_of_vechile": "34546",
"insurence": "insurance_202508210624.png",
"pollution": "pollution_202508210624.png",
"rc_ducoment": "rc_document_202508210624.png",
"vechicle_image": "[\"vechile_image2021129300.webp\",\"vechile_image1049642941.webp\",\"vechile_image1507671234.webp\"]",
"Your_upi": null,
"status": "active",
"payment_type": "1",
"publish": "1",
"dummy_data": "0",
"remember_token": null,
"created_at": "2025-08-21T06:24:35.000000Z",
"updated_at": "2025-09-05T14:59:16.000000Z"
},
"shop": {
"id": 8126,
"vender_ID": 3002,
"partner_name": "bike wale bhiyaa",
"location": "Bokaro Steel City, Jharkhand, India",
"city": "Bokaro",
"status": "active",
"latitude": "23.66929560000000",
"longitude": "86.15111200000001",
"gst_number": "213E24",
"number": "7488127637",
"website": "ramu@gmail.com",
"created_at": "2025-08-21T05:44:30.000000Z",
"updated_at": "2025-08-21T05:44:30.000000Z"
},
"vehiclebyadmin": {
"id": 91,
"vehical": "Bike",
"brand": "BMW",
"model": "C 400 GT",
"images": "[\"vechile_image2021129300.webp\",\"vechile_image1049642941.webp\",\"vechile_image1507671234.webp\"]",
"created_at": "2024-10-03T04:59:22.000000Z",
"updated_at": "2024-10-03T04:59:22.000000Z"
},
"booking": {
"id": 915,
"user_name": "Abhishek Singh",
"destination": "bike wale bhiyaa",
"vechicle_type": "bike",
"brand": "BMW",
"model": "C 400 GT",
"price": 6868,
"start_date": "2025-09-16",
"end_date": "2025-09-16",
"number": "917079488615",
"email": "abhisheksingh0860@gmail.com",
"vechicle_image": "[\"vechile_image2021129300.webp\",\"vechile_image1049642941.webp\",\"vechile_image1507671234.webp\"]",
"upi_id": null,
"user_id": 3321,
"vender_id": 3002,
"vechicle_id": "23305",
"myvechical_id": "91",
"shop_id": "8126",
"status": "9",
"rejectionReason": null,
"state": "Auto-Cancelled",
"state_timestamps": "{\"confirmed_at\":\"2025-09-05 09:29:54\",\"Paid\":\"2025-09-05 09:39:47\",\"Auto-Cancelled\":\"2025-09-05 16:00:02\"}",
"created_at": "2025-09-05T14:59:15.000000Z",
"updated_at": "2025-09-05T16:00:02.000000Z"
},
"payment": {
"id": 216,
"vender_id": "3002",
"booking_id": "915",
"vechicle_id": "23305",
"vechilebyadmin_id": "23305",
"shop_id": "8126",
"image_path": "payment_snap/payment_snap_202509050939.jpg",
"partner_name": "Rakesh kumar",
"customer_users_id": "3321",
"partner_email": "rakeshdev.cotocus@gmail.com",
"partner_number": "917488127637",
"price": "6868",
"start_date": "2025-09-16",
"end_date": "2025-09-16",
"Duration": null,
"pay_status": "0",
"reason": null,
"created_at": "2025-09-05T09:39:47.000000Z",
"updated_at": "2025-09-05T09:39:47.000000Z"
}
},
{
"id": 33,
"vendor_id": "3002",
"user_id": "3321",
"shop_id": "8126",
"vehicle_id": "23305",
"vehicle_type_id": "91",
"notification_type": "booking_paid",
"booking_id": "915",
"payment_id": "216",
"content": "Booking 915 has been marked as Paid for vehicle BMW C 400 GT. User: Abhishek Singh.",
"status": "sent",
"delivery_channel": "system",
"created_at": "2025-09-05T09:39:47.000000Z",
"updated_at": "2025-09-05T09:39:47.000000Z",
"user": {
"id": 3321,
"name": "Abhishek Singh",
"email": "abhisheksingh0860@gmail.com",
"email_verified_at": "2025-08-25T07:27:50.000000Z",
"number_verified_at": "2025-08-25 07:27:50",
"role": "user",
"number": 917079488615,
"address": "Bokaro Steel City, Jharkhand, India",
"main_location": null,
"state": "Jharkhand",
"city": "Bokaro Steel City",
"state_id": null,
"city_id": null,
"driving_lic": null,
"qrcode": null,
"profile_img": "profile_image_202509051051.jpg",
"adhar": "73834949",
"pinCode": "831020",
"company_details": null,
"status": "active",
"token": null,
"sms_notification": "1",
"email_notification": "1",
"whatsapp_notification": "1",
"created_at": "2025-08-13T13:05:33.000000Z",
"updated_at": "2025-09-05T10:51:38.000000Z"
},
"vendor": {
"id": 3002,
"name": "Rakesh kumar",
"email": "rakeshdev.cotocus@gmail.com",
"email_verified_at": "2025-08-25T10:49:19.000000Z",
"number_verified_at": "2025-08-25 10:49:19",
"role": "user",
"number": 917488127637,
"address": null,
"main_location": null,
"state": null,
"city": null,
"state_id": null,
"city_id": null,
"driving_lic": null,
"qrcode": null,
"profile_img": null,
"adhar": null,
"pinCode": null,
"company_details": null,
"status": "active",
"token": null,
"sms_notification": "1",
"email_notification": "1",
"whatsapp_notification": "1",
"created_at": "2025-08-21T05:32:29.000000Z",
"updated_at": "2025-08-25T10:49:19.000000Z"
},
"vehicle": {
"id": 23305,
"vender_ID": 3002,
"shop_id": "8126",
"vehical_id": "91",
"imei": null,
"vechicle": "bike",
"shoplocation": "Bokaro Steel City, Jharkhand, India",
"brand": "BMW",
"model": "C 400 GT",
"price": "3434",
"address": null,
"state": null,
"city": null,
"number": "KA05HC2483",
"vendor_email": "rakeshdev.cotocus@gmail.com",
"numbers_of_vechile": "KA05HC2483",
"Bookings": 1,
"available_vehicle": null,
"rc_number_of_vechile": "34546",
"insurence": "insurance_202508210624.png",
"pollution": "pollution_202508210624.png",
"rc_ducoment": "rc_document_202508210624.png",
"vechicle_image": "[\"vechile_image2021129300.webp\",\"vechile_image1049642941.webp\",\"vechile_image1507671234.webp\"]",
"Your_upi": null,
"status": "active",
"payment_type": "1",
"publish": "1",
"dummy_data": "0",
"remember_token": null,
"created_at": "2025-08-21T06:24:35.000000Z",
"updated_at": "2025-09-05T14:59:16.000000Z"
},
"shop": {
"id": 8126,
"vender_ID": 3002,
"partner_name": "bike wale bhiyaa",
"location": "Bokaro Steel City, Jharkhand, India",
"city": "Bokaro",
"status": "active",
"latitude": "23.66929560000000",
"longitude": "86.15111200000001",
"gst_number": "213E24",
"number": "7488127637",
"website": "ramu@gmail.com",
"created_at": "2025-08-21T05:44:30.000000Z",
"updated_at": "2025-08-21T05:44:30.000000Z"
},
"vehiclebyadmin": {
"id": 91,
"vehical": "Bike",
"brand": "BMW",
"model": "C 400 GT",
"images": "[\"vechile_image2021129300.webp\",\"vechile_image1049642941.webp\",\"vechile_image1507671234.webp\"]",
"created_at": "2024-10-03T04:59:22.000000Z",
"updated_at": "2024-10-03T04:59:22.000000Z"
},
"booking": {
"id": 915,
"user_name": "Abhishek Singh",
"destination": "bike wale bhiyaa",
"vechicle_type": "bike",
"brand": "BMW",
"model": "C 400 GT",
"price": 6868,
"start_date": "2025-09-16",
"end_date": "2025-09-16",
"number": "917079488615",
"email": "abhisheksingh0860@gmail.com",
"vechicle_image": "[\"vechile_image2021129300.webp\",\"vechile_image1049642941.webp\",\"vechile_image1507671234.webp\"]",
"upi_id": null,
"user_id": 3321,
"vender_id": 3002,
"vechicle_id": "23305",
"myvechical_id": "91",
"shop_id": "8126",
"status": "9",
"rejectionReason": null,
"state": "Auto-Cancelled",
"state_timestamps": "{\"confirmed_at\":\"2025-09-05 09:29:54\",\"Paid\":\"2025-09-05 09:39:47\",\"Auto-Cancelled\":\"2025-09-05 16:00:02\"}",
"created_at": "2025-09-05T14:59:15.000000Z",
"updated_at": "2025-09-05T16:00:02.000000Z"
},
"payment": {
"id": 216,
"vender_id": "3002",
"booking_id": "915",
"vechicle_id": "23305",
"vechilebyadmin_id": "23305",
"shop_id": "8126",
"image_path": "payment_snap/payment_snap_202509050939.jpg",
"partner_name": "Rakesh kumar",
"customer_users_id": "3321",
"partner_email": "rakeshdev.cotocus@gmail.com",
"partner_number": "917488127637",
"price": "6868",
"start_date": "2025-09-16",
"end_date": "2025-09-16",
"Duration": null,
"pay_status": "0",
"reason": null,
"created_at": "2025-09-05T09:39:47.000000Z",
"updated_at": "2025-09-05T09:39:47.000000Z"
}
},
]
Adding new properties
{item.user && item.user_id == userid && (
<BookingActionButton
status={item.booking.status}
paystatus={item.booking.paystatus}
booking={item.booking}
onMakePayment={() => {
setBooking({
...item.booking,
customer_users_id: item.booking.user_id, // match from booking
partner_name: item.vendor?.name || "", // safe access, fallback to ""
partner_email: item.vendor?.email || "",
partner_number: item.vendor?.number || ""
});
setGetUser(item.user);
handleMakePayment();
}}
Top comments (0)