question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Request: pass own props to `areStatesEqual`

See original GitHub issue

I want to implement areStatesEqual in such a way that it only compares the relevant state for a container. However, this relevant state might be dependent on the container’s own props. E.g. suppose my state looks like this:

{
  users : {
    1 : { /* user1 */ },
    2 : { /* user2 */ }
  }
}

and I have a container <User id={userId}>. Currently, I can’t access the id from the areStatesEqual function, and as such the best I can do is compare the entire users object. This gives a lot more false positives though, and is generally more expensive as well. If I had access to the properties of the container then I could make a much more efficient areStatesEqual function.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:7
  • Comments:11 (7 by maintainers)

github_iconTop GitHub Comments

17reactions
TiddoLangerakcommented, Sep 13, 2017

areStatePropsEqual is too low in the tree though, since it concerns the component props, not the container’s own props. areStatePropsEqual is only executed after mapStateToProps is executed, so if mapStateToProps is expensive then this isn’t ideal. The documentation itself recommends to override areStatesEqual when mapStateToProps is expensive, but without access to the container’s own props it’s not always possible to properly implement this function. To give a more complete example (with flow types for better illustration):

/*
const state = {
  users : {
    1 : { ... },
    2 : { ... }
  }
}
*/


type UserComponentProps = {
  user : User
};
function UserComponent({ user } : UserComponentProps) {
   return <div>
     {/* snip */}
  </div>
}

type UserContainerProps = {
  id : number
}
function mapStateToProps(state, ownProps : UserContainerProps) {
   // assume `getUserFromState` is expensive
   return getUserFromState(state, ownProps.id);
}

const UserContainer = connect(mapStateToProps)(UserComponent);

Now suppose I have a <UserContainer id={1}> component. I only want this component to update when the user with id=1 changes in the store. Currently these are my choices:

  • areStatesEquals: (oldState, newState) => isEqual(oldState.users, newState.users). This only prevents updates when other store slices are changed, but it still updates <UserContainer id={1}> when user with id=2 is updated.
  • areStatePropsEquals: (oldProps, newProps) => isEqual(oldProps, newProps). This does prevent the component from being updated, but it doesn’t prevent the mapStateToProps function from being called. When mapStateToProps is expensive the just having an areStatePropsEquals might not be sufficient.

If instead I could define a function areRelevantStatesEquals : (oldState, newState, oldOwnProps, newOwnProps) => isEqual(oldState.users[oldOwnProps.id], newState.users[newOldProps.id]) then I can very cheaply prevent updates to both the container and component.

14reactions
pmualabacommented, Aug 17, 2018

The change is less then 1 line of code and makes the areStatesEqual way more flexible if nextOwnProps and ownProps arguments are available to control and implement your custom rerender prevention strategy.

Since adding those to 2 arguments is completely backwards compatible, I also would like to see this PR merged… Can this again be reconsidered?

Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Connect | React Redux
The mapStateToProps and mapDispatchToProps deals with your Redux ... This also determines whether the function will receive ownProps.
Read more >
React Redux -- can I make mapStateToProps only take in part ...
I'd like it if mapStateToProps only took in the same "state slice" that I am handling in my module (like the reducer does)....
Read more >
React Redux connect(): When and how to use it
Props are read-only and allow a parent component to pass ... mapStateToProps(state, [ownProps]) => stateProps. Passing ... areStatesEqual?:
Read more >
Connect | React Redux
Connects a React component to a Redux store. connect is a facade around connectAdvanced , providing a convenient API for the most common...
Read more >
Redux's Connect function and areStatesEqual Option - Medium
allDogs hasn't changed, and so areStatesEqual returns true . This tells our program that we don't need to call mapStateToProps after all. So...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found