-
Notifications
You must be signed in to change notification settings - Fork 25.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
Router does not reuse component when switching between different Routes that use the same component. #12446
Comments
This is exactly what is going on. See example I'm logging router params https://plnkr.co/edit/iuGO8pj6DEGFkDeJMylg?p=preview |
Expanded on your example. Notice the first time you click a person, it does in fact re-init the component. https://plnkr.co/edit/UUd203Q9xo46vXNEqWmS?p=preview
|
Oh, I see. Probably reuse mechanism can be improved. |
I haven't dug into the source yet, so I'm not sure what rules are setup for reuse. I think this is a simple rule that would work: When a route changes, if the resulting component is already present in the router-outlet, don't re-render. Currently, it would seem that the rule is only applicable when you're on the exact same matching route. |
Pls update the issue title so it will be more clear what the issue is. |
Well in your example you're still navigating between routes (i.e. you've triggered a different node in your route configuration tree). It just happens that the route renders the same component in the same outlet. The parameter change stuff is irrelevant because it's a different node. I think what the docs aren't saying (but are implying) is that you only get component reuse when the navigation triggers the exact same configuration node..? That said, I'm not a team member -- I have no idea what the ultimate intent is here. |
See also #7757 (comment) |
Some background: Currently the router reuses activated routes and not components. An activated route is associated with an item in the router configuration. Since an activated route is injected in the component's constructor, we cannot reuse the same component instance when switching activated routes, at least not without introducing new primitives. We are planning to introduce custom route reuse strategies. The following issue talks about it: #7757. |
"Since an activated route is injected in the component's constructor, we cannot reuse the same component instance when switching activated routes, at least not without introducing new primitives."
|
Just a thought, the activated route could be an observable, like RouteParams, so you could still inject it, but you can watch it in case it changes. Agreed on point number 2 @vinaysoni. It does impact the whole design of the app, which is why I brought it up :). From what I've read here, I'll change how I was planning on building the app, or move over to the new Ui Router. |
@jamesmfriedman this is a very serious issue, which the router team is mistaking for a minor one. Can't believe that they have gone so complex that they can't provide a simple interface and invoke it with the active route. Any experienced single page app developer will be revolted to see the components being destroyed like this. The app is creating and destroying components all the time, as you navigate - for no obvious reason (because Framework demands that). Really funny!!! This is amateurish decision. "Just a thought, the activate route could be an observable, like RouteParams, so you could still inject it, but you can watch it in case it changes." @jamesmfriedman This is a great suggestion. Thanks for mentioning UI Router. If push comes to shove, I am glad that there is UI-Router project. |
there are easy workarounds for most use cases, therefore no need to make it a big deal |
Sorry Zoechi. I strongly disagree. |
If you tell me you can't build some kind of application because of this, then this sounds to me like you are not using Angular like it's supposed to be used. |
Sir, when you have a complex application, enterprises invest millions of dollars to build it. One can build "some kind of application" with it. That kind of people are those who are just learning Angular2 or doing a proof of concepts. But a framework that disregards such a basic tenet, needs to first realize the importance of what is missing. What you are missing is that "Not destroying the components" is how applications are built today. You are adopting the approach of destroying - and expecting developers to waste their time to recreate that state, which is unnecessary and intrusive to the UI architecture. Why are you doing this? Is it just convenient for yourself. What would be the cost of this? Especially, when mainstream community finds out, then they may use the third party UI-Router. Only a novice developer will go to the work arounds, you mentioned. Seasoned UI developers can visualize the ditch that has been dug. So, the question is why is this not high priority? Angular2 is still in early stages. Later, the more people look at it, the more people will mock it. This is very fundamental to survival of the Router. It is absolutely not about little inconvenience. One has to design every bit of the application differently with this serious limitation and one may run into issues that can never be implemented with the current approach. |
This is absolutely not the case. As mentioned they plan to add this feature. I still don't get your point. Seek out some framework Xyz in version 27.9 and be happy with it instead of complaining that the first release of of a brand-new framework has a missing feature. |
Updated my comment above. |
"I still don't get your point. Seek out some framework Xyz in version 27.9 and be happy with it instead of complaining that the first release of of a brand-new framework has a missing feature. Besides that I'm out of this discussion." You have raised a very important point without realizing it. I must explain why I don't pick up framework XYZ and be happy with it instead of complaining that the first release of of a brand-new framework has a missing feature. I think Angular2 is revolutionary in many ways. It is this one limitation that screws it up really really bad. I hope you realize this. Complaining is not bad if it can help avoid the blemish on an otherwise great framework? If I had read that this is high priority, I would not have written a single time, because I would know that this is being worked on. Once you say, that this is not high priority, I see the void between otherwise great framework and a framework with serious shortcoming. You are inventing so many other features in the Router, that is admirable. But as a UI architect, I know that without this feature all the others are just glitter. |
No matter how badly missed that feature is, if there are other more badly missed features where more developers are affected, those will get higher priority. There aren't unlimited resources, even for Google, to get everything done at once. There was a custom reuse strategy added a while back that might address your problem. |
@zoechi, appreciate the work you and your team mates put in to Angular2. I would like to see what I can do from my side to help this feature be implemented. Or I might be approaching this wrong. I have the following routes 'foo/:hello/:world/:page', component: FooComponent In the above case :page is basically a pagination of FooComponent. :world is a type and though :world changes the component FooComponent Remains the same (as you can gather). I can use query params to paginate as that solved the problem. However, I would like the switching between routes that have matching components to not re-render all of the component. I think it will have a SEO benifit to have unique path-segments in place of query params (might be better I am still testing the theory). So any suggestions would be great. Regards, |
@dewwwald I'm not on the Angular team, just an individual contributor and Angular user (just to avoid misunderstandings) |
@zoechi, sorry for that. Even more so, being an independent contributor is a huge feat. Any recommendations on the above? |
Nope. I never had that requirement. I'm fine with keeping the state in a service and let Angular recreate the component. |
@zoechi That is exactly what I am doing. However, the component subscribes to get the progress (percentage based), I am also initializing the component with 0%. So the service is like, 'oh a new subscriber, here is 50%' (trying to make the high-level discussion fun to read) and then css animation jumps from 0 to 50 after component recreation. No matter I solved it with query parameters. |
Hi @dewwwald, I think you might be interested how I achieved this goal by using custom router reuse strategy:
And setting |
@DanielKucal Thanks. I'll have a look. |
I just stumbled upon the same issue even though the documentation says it re-uses components by default: https://angular.io/guide/router#observable-parammap-and-component-reuse
|
@martinsik it does, but only when it's the same route (only route parameter change) |
@zoechi Hmm, I see. This didn't occur to me from the description. Anyway I tested it and it realy works the way you describe it. Thanks! |
@zoechi Can this behavior of component recreation be prevented? |
+1
…On Tue, Oct 31, 2017 at 5:11 PM, Appie ***@***.***> wrote:
@zoechi <https://github.com/zoechi> Can this behavior of component
recreation be prevented?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#12446 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ASVM_YERtqZB7bKsUjSDKNtiV01bpQiJks5sxwdZgaJpZM4KdieF>
.
|
@realappie see the links in #12446 (comment) |
@zoechi Thank you for the great sources, I have been reading a lot of github issues and been through a ton of commits to the point I lost track of whether the feature I need is properly implemented or not. Turns out it is, and here is a demo of that for anybody that finds it hard to implement. To use it just add a |
@realappie as others have said this only works because you are not changing to a different component altogether. Imagine a OrdersComponent and CustomersComponent. You can't switch between them without losing all unsaved state. |
I agree that this should work for a wider variety of scenarios. I have a complex component that can handle several type of urls and needs to remember the state of a tree widget that shows a hierarchy of data. Im using a service to keep that state and it's being a pain in the a**. Need to keep track of what nodes are downloaded, what nodes are expanded, etc. Lot of coding that could be saved if angular were more flexible about this. |
I know this isn't how I should accomplish this, but it actually works as far as reusing the component without any hacks in Angular 5. In this case
Any insight here? Does anyone know of another way to accomplish this without a placeholder component? |
@tommybananas ... I think that this is a correct case and using ... |
@mlc-mlapis How could this be correct when I have a component as a child of itself that contains no router outlet? I find it hard to believe that the official solution to this issue is using a placeholder component. This is a pretty common use-case. Having the normal and edit states of a resource share a component. |
@tommybananas ... you can use both URL directly ... which is fine ... probably as The component You can have even more routes combined ... Or you can use directly componentless route as ...
|
@tommybananas It works, but I feel like this is a hack since it's working around the intention of the design. I hope I am wrong. But it makes me hesitant to go this direction and worried I should not depend on it for future releases. Have you tried the solution @DanielKucal posted above? I will take a look and try tomorrow, but I use different data for each route I need to reuse. So I need the component to stay the same, but the data for the new route to be reflected. Maybe I can pass that through though. I'm not sure if this is feature is still of importance. My use case: Open to any obvious suggestions I am missing. Thanks guys. |
Just tried @DanielKucal reuse strategy above and its works awesome. Enables me to control what I want to reuse very simply. currently seems like the way to go and very simple. Thanks @DanielKucal for posting and anyone else involved. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
I'm submitting a ... (check one with "x")
Current behavior
2 or more route declarations point to the same component. If a different route matches to the same component, the DOM and component are thrown away.
/hero/1 -> /hero/2
no issue, component stays around/hero/1 -> /hero/1/powers
component is disposed ofExpected behavior
I should be able to change my route to anything and as long as it results in the same component being in the same routerOutlet, it should stay around. This is in reference to some comments in #9811
Minimal reproduction of the problem with instructions
In this example, my component should never be discarded and re-inited
https://plnkr.co/edit/T7K4TfcTdHoqJ7HaFByS?p=preview
What is the motivation / use case for changing the behavior?
in the above example,
powers
could be a tab name I want to cue off of. It could be something I ngIf on, or any other number of things.Please tell us about your environment:
MacOS, Sublimet Text, Npm
Angular version: 2.0.X
2.1.1
Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
all
Language: [all | TypeScript X.X | ES6/7 | ES5]
all
Node (for AoT issues):
node --version
=6.5.0
The text was updated successfully, but these errors were encountered: