-
-
Notifications
You must be signed in to change notification settings - Fork 15.3k
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
Sync dispatch in componentDidMount() does not update component #208
Comments
@gaearon I have confirmed this bug. In v1.0.0 the
was moved from the constructor to the To fix this, we will have to move that code back to the constructor or earlier in the component lifecycle, so it will be called before the child components call dispatch. |
Wasn't this done to prevent setState etc when doing server-side rendering? @gaearon Sent from my iPhone
|
Yes, I linked to the pull request and issue |
@taylorhakes What i meant was that moving it back to the constructor or earlier in the lifecycle will possibly have negative implications for server-side rendering. |
Correct. Another option is to document that componentDidMount dispatches need to be wrapped in componentDidMount() {
setTimeout(() => {
this.props.dispatch(/* ... */);
}, 0);
} That approach feels very brittle though. Currently React's mounting is synchronous, but it might change in the future. |
Can this behave differently depending on environment? E.g., using |
@clearjs is that exported by default? If not, it should be treated as internal file and is off limits. If it's public though, it might work. |
It's in the add-ons, so subject to more frequent changes. But the implementation is trivial: var canUseDOM = !!(
typeof window !== 'undefined' &&
window.document &&
window.document.createElement
); Obviously, this would only work in browser, not with react-native, etc. |
I think a solution which only works on the browser is not really acceptable though. |
Sorry, my last comment was confusing. It does work on Node (returns |
Here's a more robust alternative, and would work with react-native as expected: https://www.npmjs.com/package/detect-node. |
@clearjs ok that detects node. But what about other environments like ruby? You can actually do server-side rendering there too. Or even with php. They will still execute in a JS context, but that will be V8 and not necessarily node I assume. In those cases this would still break I think. |
Yep, you're right. |
Another option. What about forcing the child components to mount after the Connector? Render the children only after componentDidMount on the Connector is called. No need for environment detection. |
Forgot about server not calling componentDidMount, scratch that idea. |
Can you please turn this into a failing test? |
Also, can't we do something like componentDidMount() {
this.unsubscribe = this.context.redux.subscribe(::this.handleChange);
const nextState = this.selectState(this.props, this.context);
if (!this.isSliceEqual(this.state.slice, nextState.slice)) {
this.setState(nextState);
}
} |
I threw the example into a failing test. https://github.com/taylorhakes/redux/blob/failed-sync-dispatch/test/fullDispatch.spec.js @gaearon I think your example will work, but I don't have time to test it right now. |
I've tried v1.0.0-alpha and noticed that this small app https://gist.github.com/roadhump/f40483704e8527f11b07 will not work if I immediately dispatch action result from
componentDidUpdate
but it works if dispatch async (set constasync
to true). It worked both ways in version 0.12.The text was updated successfully, but these errors were encountered: