I have a CartStruct interface which holds a property cartObj of type CartObj. The CartObj interface holds many properties. One of which is the cartNumber.
This is the mockup of the interfaces
const interface CartStruct {
cartObj: CartObj
pos: number
}
const interface CartObj {
...
cartNumber: number
...
}
In a form, a user can input data for multiple CartStructs, and so I made a useState that stores a CartStruct array.
const [cart, setCart] = useState<CartStruct[]>([])
When the user changes the value of the cartNumber, I've found two ways to do it. One using shallow copy and this is by far more readable. The other method is to slice. It is more direct and it's definitely less readable. However, which one is more efficient? Does the fact that you're avoiding the shallow copy in the second one make the code more efficient? Is there another reason as to why one is better than the other?
Here are the methods
Method 1: Using Shallow Copies
const lst = [...cart]
lst[index].cartObj.cartNumber = e.target.value
setCart(lst)
Method 2: Direct approach
setCart([
...cart.slice(0, index), {
...cart[index],
cartObj: {
...cart[index].cartObj,
cartNumber: e.target.value
}
},
...cart.slice(index 1)
])
CodePudding user response:
First of all Method 2 is also a shallow copy, you start by doing ...cart
.
The difference is that in Method 2 you also shallow copy all the objects in the path to your change - this is called an immutable update. btw, there are libraries that can do it for you, to make it more readable, like: react immutability helper or immer.
Method 1 is slightly faster. but Method 2 is more correct. Because although React renders all the child components when a parent is rendered by default, you might memoize one of the child components (using React.memo) and then this component will only render if its' props or state changed by reference (unless you use context).
One final note, I don't know how many items you have in the cart. And nothing about your state management. But if it's a very long list of items and performance matters you might want to pass the parent component only a list of itemIds and let the child component get the correct item by id. This way the parent component won't render when a field is changed inside an item.
Good luck