0

Problem

I have two inputs that triggers an event, which will update an quantity of a certain product (Those inputs are referenced to a product).

And since I can write an number, for example, the quantity, very fast, it is usually slow.

Takes 1-2 seconds (When I have more products) to update the quantity of the product...

The function that updates the product will return a new basket which is basically the "cart", where all products are, and then I'll update the old one with the new one (with the modifications).

What kind of performance improvement should I implement?

Note: I'm using React and the function belongs to a Context API.

Method: modifyProductQuantity()

export const modifyProductQuantity = (
  productToModify: ProductInterface,
  quantity: number,
  basket: ProductInterface[]
): ProductInterface[] => {
  const basketWithUpdatedProduct = basket.map((product) => {
    if (product.id === productToModify.id) {
      const totalPrice = product.pricePerMeasurement * quantity;
      const roundedTotalPrice = parseFloat(totalPrice.toFixed(2));
      const roundedTotalQuantity = parseFloat(quantity.toFixed(2));
      return {
        ...product,
        quantity: roundedTotalQuantity,
        price: roundedTotalPrice,
      };
    }
    return product;
  });
  return basketWithUpdatedProduct;
};

My Possible Solution:

I might be able to achieve a better performance if I handle the product modification in the background, and it works like this:

  • Every time I change the input I run a setTimeOut of 3 seconds, for example.
  • If I change the input again, another setTimeOut will be run.
  • Therefore I would only run the function when the user stops typing

What do you guys think???

odas0r
  • 31
  • 1
  • 5
  • `basketWithUpdatedProduct` has a long length? – kyun Nov 16 '20 at 02:52
  • The solution you explained is called debounce. – Jacob Smit Nov 16 '20 at 02:53
  • It doesn't. It can go to 20 maximum! But I've seen that as I add products, like 6, it will become slower, taking 1 second as I change the input value (Quantity) @kyun – odas0r Nov 16 '20 at 02:55
  • Excellent, thank you @JacobSmit. I think I can achieve what I want with that, or do you think there's a better way? – odas0r Nov 16 '20 at 02:57
  • Actually updating the value in memory shouldn't be slow, particularly with only like 6 objects. What's likely causing the slowness is the re-rendering. Do you show all cart items on the screen at the same time? Have you done a performance test and checked how long components are taking to render? – Jayce444 Nov 16 '20 at 03:05
  • You could possibly restructure how you are storing your basket to be quicker to access. You can use an object with the properties named with the IDs of your products meaning that access could be as easy as `object[product.id]`. This older question might shed some light: https://stackoverflow.com/questions/17295056/array-vs-object-efficiency-in-javascript – Jacob Smit Nov 16 '20 at 03:05
  • @Jayce444, That's why I asked this. I was not sure if this was just a problem of using Context API, if it was the re-renders, or even using .map. But yes I think I might have failed in this part somewhere. Yea, I show all cart items at the same time, and I need to do a performance test actually to check all of that, but since this is something not so complex, I didn't do it... I think i'll do that first to find those mistakes in the code – odas0r Nov 16 '20 at 03:19
  • @JacobSmit Hmmm, thanks!!! I'll definitely check that approach, and see what I can do! – odas0r Nov 16 '20 at 03:22
  • @odas0r you can use the performance tab in Chrome to do a quick 10 second profile of you interacting with the cart when you have 6+ items, then check under the "Timings" section to see what's slowing you down. Might be that the cart items need some root level memoizing, so that changing one doesn't cause full component tree re-render – Jayce444 Nov 16 '20 at 03:23
  • Perfect, i'll give that a try, see what I can do!! Thank you so much – odas0r Nov 16 '20 at 03:27

2 Answers2

0

After some debugging & refactoring I improved the performance slightly, but it wasn't not enough for me.

The solution was implementing a debounce method using Hooks (thanks to Jacob Smith), as I mentioned in the Possible Solution section.

Here's a good blog post on how to create that hook

odas0r
  • 31
  • 1
  • 5
0

for performance optimization, you can follow these steps:

  • debouncing: you have already mentioned this performance optimization technic for more information about debouncing and how to implement this one in react you can check this
  • how to implement debouncing in react
  • what is debouncing and throttling
  • useCallback hook: you can use this hook to memoize your function. so that it can hold some results for future references. you can read more about this
  • more about useCallback
  • using proper dataStructures: we know that finding an id in an array of objects takes O(n) times. we can convert that array into Maps so that in O(1) time we can identify the object to be updated also Maps are iterative in nature so it will solve the purpose of Array here in your case.
  • Note: data structures and architectures play important role in optimization than fancy technics like hooks and debouncing etc.
DilipCoder
  • 548
  • 1
  • 6
  • 17