Handling States in React: Part 6
Codenova
Blockchain & Web Development Company
Handling Complex states in React : Nested Objects
Real World Applications will have a lot of moving parts and interactive elements. I would like to go in depth for this topic.
First we need to understand the Data types in JavaScript and how it is stored in the memory.
- Primitive (String, Number, Boolean, Undefined, Null)
- Non-Primitive (Object, Array, Function, Date, … etc)
Memory types
- Stack Memory
- Heap Memory
Stack Memory
Think of stack memory like planning your day. It is done quickly, with to-do items listed one by one according to decreasing priority. Tasks are completed in a LIFO (Last In, First Out) fashion, meaning the last item added is the first one removed. Primitives are stored in Stack
Heap Memory
While stack memory is like planning your day with a list of tasks that you quickly add and complete, heap memory is like managing long-term project files. These files represent complex data structures that you need to store and access over an extended period. Non Primitives are stored in Heap.
Now that we understand data types and how they are managed in JavaScript, let’s revisit states in React.
In Part 1 of this series I explained Objects vs Individual States in React.
This is how you update a Primitive state in React
Primitives in State
This is how you update a Non-Primitive state in React
Non Primitives in State
Notice the incrementCount function in both the images, and how the new count is updated. In the first image the count is passed directly. In the second image an entire new object is returned in the setState function. Well then the question arises
Can we update the object like this ?
const incrementCount = () => setState( (prevState) => {
prevState.count = prevState.count + 1
} )
The answer is no. This is because non-primitive data types are stored in heap memory, and their reference is stored in the stack for faster access. When you change the property of an object, the reference to the object remains unchanged. It is always recommended to return a new object when setting states in React.
Ok now what if there is a slightly complex object in the state ? Something like this
{
"categories": [
{
"id": 1,
"name": "Electronics",
"products": [
{
"id": 101,
"name": "Smartphone",
"brand": "Brand A",
"price": 699.99,
"specifications": {
"screenSize": "6.1 inches",
"batteryLife": "24 hours",
"storage": "128 GB"
},
"reviews": [
{
"id": 1001,
"user": "User1",
"rating": 4.5,
"comment": "Great phone with excellent battery life."
},
{
"id": 1002,
"user": "User2",
"rating": 4.0,
"comment": "Good value for the price."
}
]
}
]
},
{
"id": 2,
"name": "Home Appliances",
"products": [
{
"id": 201,
"name": "Refrigerator",
"brand": "Brand C",
"price": 899.99,
"specifications": {
"capacity": "500 L",
"energyRating": "4 stars",
"features": ["Frost Free", "Inverter Compressor"]
},
"reviews": [
{
"id": 2001,
"user": "User5",
"rating": 4.7,
"comment": "Spacious and energy-efficient."
},
{
"id": 2002,
"user": "User6",
"rating": 4.3,
"comment": "Quiet operation and good cooling."
}
]
}
]
}
]
}
How do you update the Home Appliances 1st product 2nd review’s rating ?
Your head hurts just thinking about it right ?
Here’s how to do it…
const updateReviewRating = () => {
setState(prevState => ({
...prevState,
categories: prevState.categories.map(category =>
category.id === 2
? {
...category,
products: category.products.map(product =>
product.id === 201
? {
...product,
reviews: product.reviews.map(review =>
review.id === 2002
? { ...review, rating: 4.8 }
: review
)
}
: product
)
}
: category
)
}));
};
Is there a simpler way to do this ?
const homeAppliances = state.categories.find(category => category.id === 2);
const refrigerator = homeAppliances.products.find(product => product.id === 201);
const review = refrigerator.reviews.find(review => review.id === 2002);
if (review) {
review.rating = 4.8;
}
We can definitely do something like that.
I’ll implement this in the Quiz Application that I am building. Stay tuned…
References and credits.
