components
components copied to clipboard
virtual-scroll: attempted to use view after destroyed errors
These occasionally pop up, need to investigate root cause
I am getting these a lot!!!! As a temporary workaround, I added a simple check to see if the view is destroyed in CdkVirtualForOf._updateContext. Although this makes my browser console window less red, I imagine there is an underlying problem somewhere else.
Here is my patch:
CdkVirtualForOf.prototype['_updateContext'] = function (this: any) {
const count = this._data.length;
let i = this._viewContainerRef.length;
while (i--) {
let view = this._viewContainerRef.get(i) as EmbeddedViewRef<CdkVirtualForOfContext<any>>;
if (!view.destroyed) {
view.context.index = this._renderedRange.start + i;
view.context.count = count;
this._updateComputedContextProperties(view.context);
view.detectChanges();
}
}
}
@grant77 are you seeing this with autosize strategy or fixed size strategy? so far I've only seen it with autosize
Fixed size strategy.
If you're able to create a reproduction I'd love to see it, would probably be easier to debug with the fixed size strategy
I'll try to put something together tomorrow.
Here you go:
https://stackblitz.com/edit/angular-material2-issue-huoqn3
Note: My VirtualDataSource is a work in progress. Basically, I am trying to pull data in chunks from my API as they scroll. You should get a plethora of errors as you scroll. The error is:
** ERROR Error: ViewDestroyedError: Attempt to use a destroyed view: detectChanges
@grant77 Thanks for the repro. After some experimentation, it looks like the errors are happening when the length of the data shrinks to be smaller than what the user is currently viewing. I'll look into how to fix it. Aside from this bug there's probably something strange going on with your DataSource that you may want to look into. I can't tell from looking at it why the data length would be constantly changing
Your welcome. Thanks for fixing #12869 so quick. I have forked the demo above and added three things:
- The fix you gave me from #12869 regarding viewChange inside zone. I removed the setInterval hack.
- Uncommented the patch for CdkVirtualForOf._updateContext that suppresses the errors so you can see what I am logging.
- tap(data => console.log(data.length)) as last rxjs thing in DataSource to write the data length.
https://stackblitz.com/edit/angular-material2-issue-eeiups
I don't see it logging anything but 10000.
Hmm, ok maybe I'm wrong then. Your data source must be doing something interesting that I'm not capturing.
I tried to make a simpler DataSource
for the sake of debugging: https://stackblitz.com/edit/angular-material2-issue-nxvupb?file=app/app.component.ts I noticed that this one is fine if I leave the length constant, but if I uncomment the line randomizing the length and scroll to the end of the list I start to get the same kind of errors. I assumed yours must be having similar issues, but it sounds like maybe something else is going on
This is mind-boggling. I modified your demo a little bit, and now I can get the errors again, but not as easily as I could with my demo. You have to jerk the scrollbar back and forth. Here you go:
https://stackblitz.com/edit/angular-material2-issue-ijb5fc
If it's helpful, I have another test case. Steps:
-
Open Chrome mobile simulator (not necessary, but makes the issue more consistently reproducible for me)
-
Navigate to https://websign.cyph.wang/simple-master#account
-
Login in with username
elon
and passwordhunter2
-
Quickly scroll up and down a bunch of times
This is what the relevant code looks like:
<cdk-virtual-scroll-viewport
fxFlexFill
[itemSize]='86 + ((envService.isMobile | async) ? 8 : 16)'
class='contact-list'
>
<ng-container *cdkVirtualFor='
let item of filteredContactList; trackBy: trackByUser
'>
<ng-container *ngTemplateOutlet='listItem; context: {
item: item
}'></ng-container>
</ng-container>
</cdk-virtual-scroll-viewport>
Also seeing this issue and it appears quite a lot when the collection is updated. Can't seem to figure out exactly what's happening, but I can trigger it consistently if I filter the collection by certain items. Although once it's been triggered the first time, it can happen randomly (and sometimes even in an infinite loop).
I had similar issues but managed to completely overcome it by fiddling with the templateCacheSize:
<div *cdkVirtualFor="let item of items; templateCacheSize: 100" class="example-item">{{item}}</div>
See documentation at https://material.angular.io/cdk/scrolling/overview
@Kim-Andersen thanks for the tip - seems to solve the issue for me!
I've just noticed in our code that the trackBy code was using an incorrect function signature (it was comparing on the first parameter which is index and not the item in the list). Since fixing this, I'm not seeing the issue so far (even without the templateCacheSize change).
@Kim-Andersen - Thanks Kim. Your solution worked for me. I know in recent version of material they fixed this issue but I really dont have scope to upgrade the version as my application is live and there is no plan to invest on the upgrade task