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.stringify
ing 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:
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.
state
is something "owned" by that component (noteworthy: not all components need state at all!). 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.