Skip to content

Parent component is not re rendered when child triggers state change in componentWillMount for SSR #597

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

Closed
dlebedynskyi opened this issue Jan 6, 2017 · 1 comment

Comments

@dlebedynskyi
Copy link

dlebedynskyi commented Jan 6, 2017

This might be expected behavior- in this case I'd really appreciate explanation for it.

tl;dr;

For SSR parent component render is not triggered if child updates shared state. Client browser renders as expected.

Issue details

we have App.jsx - all it does is adding no-scroll class for container when Modal window is rendered.

// simplified 
const mapStateToProps = state => ({
isNoScroll: !state.modal.visible
})
const App = ({children, isNoScroll}) => (
<div className={cx('app__root', {'no-scroll': isNoScroll})}> 
{ console.log(`App rendered with ${isNoScroll}` }
 {/* rest of stuff*/}
{children}
</div>
)
export default connect(mapStateToProps)(App);

Modal is using componentWillMount to dispatch state change

const mapDispatchToProps = dispatch => ({
  onShow: () => dispatch(toogleModal(true)),
});

export class Modal extends Component {
  componentWillMount() { this.props.onShow(); } 
  render() { <div> {this.props.children} </div>}
}
export default connect(() =>({}), mapDispatchToProps)(Modal);

Somewhere in app we use <Modal>stuff</Modal>. Modals have url and can be directly refreshed in browser like /profile/modalStuff using RR v4.
We have SSR and when page source is viewed we can see that state.modal.visible === true - meaning that componentWillMount was triggered and redux state got updated.
Client in this case renders no-scroll class as expect. At the same time server does not have this class name added. Causes react warning.

also if you look at server console you will see that

App rendered with false

instead of expected 1 false and 2 true.

Client side on other hand when opening modal in browser will log false and true as expected.
It looks like state change done in componentWillMount never triggered rerended of App.jsx on server while it does so on client.

calling render on server side again for 2nd time causes App to have correct class again.

Any thoughts on this?

Version

React 15.4.1
react-redux 5.0.1

@timdorr
Copy link
Member

timdorr commented Feb 17, 2017

You can't dispatch from cWM because that will change the state the render is using, which is a synchronous operation on the server. It can't rewind back and update things it's already rendered. You'll have to "preload" your state on the server by determining what actions need to be dispatched, resolving them (if they're async), and then going on to render.

#210 might be helpful here.

@timdorr timdorr closed this as completed Feb 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants