-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use transactional setState() inside connect() #368
Comments
Looking into it! I'm trying to wrap my head around what would no longer be necessary. Looks like this could clean up quite a bit of hand holding around |
Making progress. 8 failing test mostly around invocation counts. Will work on this more tomorrow. |
Awesome! If you get stuck please feel free to share your work in progress so somebody can pick it up later. |
Really happy to see all those red lines on first commits :) |
ApproachMy approach was to use I also added the following lines which needs to be run if required.
Whats pendingconditionally run
I can work on it tomorrow. If someone wants to continue feel free to use what I have done. |
@gaearon Now i'm stuck! I've gotten all but 3 test to pass:
I had to update one test now that re-rendering is now driven by setState. I think test failures 2 and 3 are similar issues. Test failure 1 is a bit different and @gaearon I was hoping you can look at it for me. My notes: https://gist.github.com/amccloud/327a9d7b7dc97eaf6bb3f1f3da9e2d5e |
@gaearon is there a reason why the test |
@gaearon it was quite hard and the code is not clean yet but I made all tests pass! You can take a look at [#373] At first I thought that I would never be able to make pass the last test related to the stale props when both parent/child are connected, because the transactionnal setState callback can be called multiple times in a single batch. I had to use a trick like that: this.lastSetStateFunction = setStateFunction
this.setState((previousState, currentProps) => {
if ( this.lastSetStateFunction === setStateFunction ) {
return setStateFunction(previousState,currentProps)
}
else {
return previousState
}
}); @tgriesser I also succeeded make all the tests pass without using |
We currently delay calling
mapStateToProps
andmapDispatchToProps
in the common case because it is too early to supplyownProps
insidehandleChange
, as those props may themselves be obtained from the previous version of the state by the parent component, and may not have been received as the new props just yet, so we bump into issues with staleness (#86).Right now we call them inside
render()
soownProps
are always up-to-date but this is a bit odd, makes the code complicated and in some cases robs us of possible performance improvements, as caching the element isn’t quite as good as providingshouldComponentUpdate
(#366).One possible solution to this would be to use the transactional
setState()
overlordoverload.It is described in the documentation:
This looks pretty much exactly like our use case, and I have a feeling that this would let us use
setState
normally without having to resort to callingmapStateToProps
and friends inrender()
. In this case, we would probably keep the merged props rather than the store state, in the local state.We still want to keep the “fast path” that avoids
setState
altogether inhandleChange
, but other than that, the rest of the code should be vastly simplified by this, or at least become more conventional.I’m still not 100% sure this is going to work, but I encourage anyone who wants to dig deeper into how React and Redux work together to give this a try. We have an extensive test suite that should cover any call count regressions. If you are working on this, please leave a comment in this issue.
The text was updated successfully, but these errors were encountered: