tripRev
tripRev

Reputation: 912

Normal/Standard way to compare prevProps in componentDidUpdate

This has come about because during prototyping, I'm finding that incoming new prop(s) might be an array of complex objects, so prevProps.myProp===this.props.myProp is always false. JSON.stringifying them both before comparison works, but feels unreliable.

I'm trying to write a reusable function for Class Components that compares prev/new props in react's componentDidUpdate. For example:

componentDidUpdate(prevProps) {
    // First, get difference here, possibly using a lib like npm 'deep-object-diff'.
    // ...or just JSON.stringify both and do string comparison
    const changes = getTheDifference(prevProps, this.props)

    // Don't do anything if there's no changes.
    if (!changes) return

    // Then I want to do something like:
    this.setState( Object.assign(this.state, changes) )
}

...that would mean any time the incoming props change, those get immediately reflected in state. I'm having some issues finding a suitable diff lib, but I still feel like I shouldn't be having to do this and am missing something - is there a generally accepted "normal" way to do this, or is me having this problem just a sign of:

Upvotes: 0

Views: 486

Answers (1)

Adam Jenkins
Adam Jenkins

Reputation: 55792

that would mean any time the incoming props change, those get immediately reflected in state

Yes, that's wrong. When I first started out I was doing the same thing.

  1. state is something "owned" by that component (noteworthy: not all components need state at all!).
  2. props are something that are "owned" by a higher component.

Best example:

ComponentA passed an id to ComponentB as a prop. ComponentB uses that id to make an API request (for example).

The status/results of that API request form part of ComponentB's state (it's "owned" by your component). The id passed in as a prop is NOT part of ComponentB's state (it's owned by ComponentA, or maybe somewhere higher in the tree that passed it as a prop to ComponentA).

When the id prop changes, ComponentB will need to make another API request.

EDIT:

The complexity of lifecycle methods is why React has highly encouraged functional components.

You should think of components as functions. It's a lot easier to write the logic if you just think of it as input -> output.

componentDidUpdate has been moved to useEffect with a dependency list so you can say - run this function, but only when this prop changes - which is a nice way to break down massive componentDidUpdate methods into tiny readbale/testable chunks.

I've heard a lot of people say hooks ruined react, but I highly disagree with them. React saw the problems people were running into in the community by misusing class/instance based components and instead of lecturing about how to use them correctly, they nudged people to writing better components by introucing a simpler API - functions, while they still can and will be abused - are generally simpler to deal with than classes and align nicely with composition over inheritance and declarative over imperative.

Upvotes: 2

Related Questions