-
-
Notifications
You must be signed in to change notification settings - Fork 10.5k
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
Updated history subscription in ConnectedRouter #5203
Conversation
Moved history subscription from componentWillMount to componentDidMount to avoid memory leaks during server side rendering.
Thanks! |
@klis87 Where is the memory leak that this pull request purportedly fixed? It's true that when using SSR we're adding a subscription without explicitly removing it, however how is that a memory leak? Your history objects are created and garbage collected before/after each request. The listeners are not global, they're simply added to a scoped array, which will itself be garbage collected: This change broke the core functionality of The listener was added in Additionally, as someone using SSR, I want this listener registered on my server. We need this action dispatched so we can inspect the redux store and perform server-side 302 redirects. @timdorr Could you please role this back and push a new beta release to NPM? You should then be able to close off #5655. |
I completely agree with @Benjamin-Dobell this PR adds more issues than it tries to solve. Another example is that the following test won't pass: it('redirects properly', () => {
expect(store.getState()).toHaveProperty('router.location', null)
renderer.create(
<ConnectedRouter store={store} history={history}>
<Switch>
<Route path="/test" render={() => null} />
<Redirect to="/test" />
</Switch>
</ConnectedRouter>
)
expect(store.getState()).toHaveProperty('router.location.pathname', '/test')
}) Because the subscription will take place after the redirect. I think that this should be undone, I'm currently preparing a PR to undo this, while adding this test. |
The listener is never cleaned up on an SSR render. |
That's also why we noop listening in |
@timdorr What do you mean by the listener is never cleaned up? Is it not garbage collected along with everything else (all the rendered components etc)? What led you to believe otherwise? The only reason it won't be garbage collected is if there's a global (or active) reference back to the history object or the EDIT: Note that browsers (and JS VMs) use garbage collection and resolve cycles, not ARC (like iOS). The fact that |
That may be some legacy thinking from 2.0/3.0. I had an app that maintained a common history instance to avoid some creation overhead on each request. I just reset The downside of this leaving hanging subscriptions does remain. That can cause problems if you rely on the history instance after rendering. But that's fairly uncommon at this point. |
@timdorr I guess if you're wanting to support reusable I think in general the reuse of state between server-side renders is a bit of an anti-pattern, however if that is being done with history, then ideally I think that ought to be a concern of the "history" project and not "react-router". |
Alpha 9 is up. We'll get this right at some point... |
@timdorr Woah! That was quick. Awesome maintenance, very much appreciated! |
Moved history subscription from componentWillMount to componentDidMount to avoid memory leaks during server side rendering.