React - avoid re-rendering an object property

I have an auction object and for the sake of the argument let’s say this object contains only 2 properties; remainingTime and amount. I have set up a countdown timer (I used react-countdown-now library) for the remainingTime, I also have a button to make an offer, when this button is clicked an offered is added with the amount equal to current amount + 5.

All this works, the problem is that whenever I click the offer button React re-renders the whole component and that resets my timer and I don’t want that. How can I tell React to not re-render the remainingTime property?

code: https://codesandbox.io/s/x27j7kqxrq

Generally, use PureComponent instead of Component (or use the shouldComponentUpdate() lifecycle method and set it to return false, which is basically the same as PureComponent).

I never heard of PureComponent before, is this something that only classes have access to?

edit: It seems like I have to turn my functional component into a class to be able to use those options that you mentioned.

BTW, in shouldComponentUpdate() I am going to to return false that specific property, correct?

Yes, function components will always rerender: if you want to prevent rerender you have to convert them. PureComponent is basically just Component with shouldComponentUpdate prefilled as false, so it’s generally better to use that rather than manually defining shouldComponent...

Umm… The documentation don’t say much about PureComponent, I mean there’s no real example that could serve me as a guidance. But I read somewhere else and basically what I had to do is the following:

import React, { PureComponent } from "react";
import Countdown from "react-countdown-now";

class Auction extends PureComponent {
  render() {
    return (
      <div>
        {this.props.data.map(el => (
          <div key={el.id} className="flex">
            <h1>{el.amount}</h1>
            <h1>
              <Countdown
                date={Date.now() + el.remainingTime}
                daysInHours={true}
              />
            </h1>
            <button type="button" onClick={() => this.props.onOffer(el)}>
              Add offer
            </button>
          </div>
        ))}
      </div>
    );
  }
}

And React should take care of it, but it keeps re-rendering the whole component.

Ah, I see, in this case, yes it will rerender because you’re updating all the props. It makes no difference if you use PureComponent or not because you’re telling it to rerender. I think you’re going to need to implement a custom function in shouldComponentUpdate, or whatever the callback actually does needs to do some kind of a forced update. Clicking that is updating the props on this component, you need to make it so that it does not do that — as soon as you update props that says to React that you need to rerender

So I need to use componentShouldUpdate to fix this bug? I hardcoded a value that is not related to my auction object to my <CountDown /> and it’s still re-rendering when I click the offer button.

What I mean is that you are updating the props on Auction — I don’t know what the callback does so I can’t see how — and once you do that it has to rerender, and once it rerenders, you map over the data prop again. The shouldComponent... method does a comparison to see if it needs to rerender, but if you update the props it has to rerender.

What I mean by a custom function is you would need to specify some condition under which the component should not rerender. This may not work anyway the more I think about it, so instead you need to make sure that you are not updating the props on Auction, which is likely to mean you’ll need to rethink the way your components are structured

I may be late to the party, but you would need control over the ticking part yourself.
Because you have to update the remaining time in your state everytime the timer ticks, so when someone clicks Add button, the component will rerender but with the latest time because the state contains the latest time.

Here’s how it would look like:

React-countdown-now gives a prop controlled which you need to set it to true and implement your own ticking function to sync the state.