Skip to content
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

Component from previous route are staying in memory while navigation to a different route. #13702

Closed
zero1hac opened this issue Sep 20, 2018 · 5 comments

Comments

@zero1hac
Copy link

Do you want to request a feature or report a bug?
bug

What is the current behavior?
I am using react-router for making a single page application which have multiple routes. While navigating between the routes, I noticed that the component from the previous route is still present in the memory e.g. If I navigate from route1 to route2, I can see that component corresponding to route1 is still in the memory. Moreover, if I change my route from route1 to route2 then route2 to route3, the component from route1 is cleared out and route2 component is still in the memory while I am at route3.

Adding heap snapshot for this unexpected behaviour :
react1

CodeSandbox demo for reproducing the same: Demo

What is the expected behavior?
Ideally, component corresponding to the previous route must be completely removed from the memory when we navigate to the new route. Or there must be some rule if we are keeping it for some optimizations.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
react 16.4.2
react 16.4.2
react-router-dom 4.3.1

@gaearon
Copy link
Collaborator

gaearon commented Sep 20, 2018

AFAIK it's expected that a component one level deep would be retained until the next update which would clear it out.

// Cut off the return pointers to disconnect it from the tree. Ideally, we
// should clear the child pointer of the parent alternate to let this
// get GC:ed but we don't know which for sure which parent is the current
// one so we'll settle for GC:ing the subtree of this child. This child
// itself will be GC:ed when the parent updates the next time.

If you're seeing a deeper tree not getting GC'd, please make sure you're checking with a production version and include exact steps you were doing to diagnose it.

@abhikmitra
Copy link

abhikmitra commented Sep 20, 2018

@gaearon So we investigated this . If you see the screenshot below, you would see that route 3 (test3) has a deep nested react components each with a huge state.

When I go to route 4 (test 4 - see the heap snapshot below) not only the root component but the nested child along with its state is there. As a result the route memory for test4 bloats up.

It gets only garbage collected in route 5. While debugging we could see (as you mentioned above) that during reconciliation it gets gc-ed while creating the next WIP tree when the previous fibers are used and effects(nextEffect, firstEffect, lastEffect) is wiped out. So the references to Test3 get removed at this line in ReactFiber.js

But the parent of Test3 which is the route component of type (ƒ Route()) still keeps a reference to Test3 using its lastEffect. The lastEffect is reset when the fiber gets reused in the code pointed above.

So from the behaviour it seems, a fiber node even though its disconnected from parent , child and alternate using the detach fiber can still have references to it from other fibers using the effects array.

Also this is reproducible in the production version as well.
Here are the detailed Repro Steps

  • Load the sandbox
  • Navigate to Route 3 and take memory snapshot
  • Navigate to route 4 and take memory snapshot (All the route 3 components still persist)
  • Navigate to route 5 and take memory snapshot (All the route 4 components still persist, route 3 is gone)
  • Wait for 10 seconds for it trigger a state change automatically , and take memory snapshot (route 4 is gc-ed)

screen shot 2018-09-20 at 10 09 13 pm

@gaearon
Copy link
Collaborator

gaearon commented Nov 1, 2018

So from the behaviour it seems, a fiber node even though its disconnected from parent , child and alternate using the detach fiber can still have references to it from other fibers using the effects array.

I think this makes sense. Thanks for explaining.

@stale
Copy link

stale bot commented Jan 10, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution.

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Jan 10, 2020
@stale
Copy link

stale bot commented Jan 19, 2020

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants