-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
Issue with assigning lazy loaded standalone components environment injectors #50724
Comments
I've created a minimal reproduction that doesn't use lazy-loaded components or the router here: https://stackblitz.com/edit/angular-extdt1?file=src%2Fmain.ts The issue is that your components have the same selector. I'm not sure why this causes this behavior (edit: see my comment below for why), but you can see the NG0912 warning (https://angular.io/errors/NG0912) in the console. The issue goes away if you fix the duplicate component id issue in any of the ways described by the NG0912 docs. |
I think the root cause is that standalone component injectors are cached by their component id here: angular/packages/core/src/render3/features/standalone_feature.ts Lines 26 to 41 in 4550fe4
This explains why the order of component activation matters for your reproduction. When the second component is created, it's pulling the injector from the cache instead of creating a new one like you'd expect. |
Thnx for digging into it @garrettld - this raises an interesting question of using component's id as a key in the |
@pkozlowski-opensource agreed, the component ids that we generate based on the metadata may have collisions. We plan to improve their generation further (by using more fields, including |
…tances Prior to this change, we've used `componentDef.id` as a key in a Map that acts as a cache to avoid re-creating injector instances for standalone components. In v16, the logic that generates the id has changed from an auto-incremental to a generation based on metadata. If multiple components have similar metadata, their ids might overlap. This commit updates the logic to stop using `componentDef.id` as a key and instead, use the `componentDef` itself. This would ensure that we always have a correct instance of an injector associated with a standalone component instance. Resolves angular#50724.
…tances (#50954) Prior to this change, we've used `componentDef.id` as a key in a Map that acts as a cache to avoid re-creating injector instances for standalone components. In v16, the logic that generates the id has changed from an auto-incremental to a generation based on metadata. If multiple components have similar metadata, their ids might overlap. This commit updates the logic to stop using `componentDef.id` as a key and instead, use the `componentDef` itself. This would ensure that we always have a correct instance of an injector associated with a standalone component instance. Resolves #50724. PR Close #50954
…tances (angular#50954) Prior to this change, we've used `componentDef.id` as a key in a Map that acts as a cache to avoid re-creating injector instances for standalone components. In v16, the logic that generates the id has changed from an auto-incremental to a generation based on metadata. If multiple components have similar metadata, their ids might overlap. This commit updates the logic to stop using `componentDef.id` as a key and instead, use the `componentDef` itself. This would ensure that we always have a correct instance of an injector associated with a standalone component instance. Resolves angular#50724. PR Close angular#50954
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. |
…tances (angular#50954) Prior to this change, we've used `componentDef.id` as a key in a Map that acts as a cache to avoid re-creating injector instances for standalone components. In v16, the logic that generates the id has changed from an auto-incremental to a generation based on metadata. If multiple components have similar metadata, their ids might overlap. This commit updates the logic to stop using `componentDef.id` as a key and instead, use the `componentDef` itself. This would ensure that we always have a correct instance of an injector associated with a standalone component instance. Resolves angular#50724. PR Close angular#50954
…tances (angular#50954) Prior to this change, we've used `componentDef.id` as a key in a Map that acts as a cache to avoid re-creating injector instances for standalone components. In v16, the logic that generates the id has changed from an auto-incremental to a generation based on metadata. If multiple components have similar metadata, their ids might overlap. This commit updates the logic to stop using `componentDef.id` as a key and instead, use the `componentDef` itself. This would ensure that we always have a correct instance of an injector associated with a standalone component instance. Resolves angular#50724. PR Close angular#50954
Which @angular/* package(s) are the source of the bug?
core/router
Is this a regression?
No
Description
Noticed some odd DI/Router behaviour,
I have 2 lazily loaded standalone components, each loading from different routes, each importing an NgModule that provides a service.
Source here https://stackblitz.com/edit/angular-n7t8rb, you may have to visit this first to get the links below working.
If I visit https://angular-n7t8rb.stackblitz.io/ and then click the “lazy two” button, I get a DI error.
If i visit https://angular-n7t8rb.stackblitz.io/two it loads successfully. Why would this work when the router-based navigation above did not? When i click the “lazy one” button to load the other lazy component, theres a DI error.
I’ve logged the injectors created by each component as they render, it looks like the first Lazy component that gets loaded is the one that gets a new Environment Injector, the second does not, causing the DI error. We get an R3 injector for App and 1 for either LazyComponent or LazyTwoComponent, based on which loads first. I think this is related to the usage of
loadComponent
I made another example with
loadChildren
for one route andloadComponent
for the second, https://stackblitz.com/edit/angular-3ffdoh. In this case we get no errors and an R3 injector for App, LazyComponent and LazyTwoComponent, which seems to me like the expected behavior.The text was updated successfully, but these errors were encountered: