naver / egjs-infinitegrid

A module used to arrange card elements including content infinitely on a grid layout.
https://naver.github.io/egjs-infinitegrid/
MIT License
2.2k stars 94 forks source link

Svelte re-displaying different amounts of items issue #530

Open NathanaelA opened 1 year ago

NathanaelA commented 1 year ago

Description

So I have a MasonryInfiniteGrid filled with 600+ items, and a filter box, when I filter it down and then remove the filter the grid starts having issues displaying all the items again. I've verified multiple ways that all the items are present in the dataset sent to the MasonryInfiniteGrid, but it seems to have some weird glitching re-calculating the new grid size.

Sometimes it does this: image You can see the scroll bar, it knows there are supposed to be about 500 more items, but the rest of the scroll area is blank, it only displayed the rows up to the point where the prior filtered amount had it.

Most the time it does this: image Where instead of making the grid larger, it keeps the same number of rows as the original filtered set, (so the filtering the results produced ~101 items, so 7 rows filled, and 1 partially filled row. Removing the filter made it be 104 items exactly 8 rows filled.

Looking at the HTML, the grid didn't created any more than the 104 items in the html, despite the displayItems being set to an array of 668 items currently.

Frequently it used to actually flash one or two of the Items, and then display nothing. I found out that the getStatus() I could get some of the internals... The getStatus function returns a containerManager and it had the rect.height === 0. Which is wrong, so I figured out that in that case telling it to updateItems() with or without the current item array would "fix" it. Unfortunately, I thought I was fixing the issue but as more testing has happened, I started noticing the above two issues so it doesn't actually fix the issue it just partially masks it and instead creates one of the two above issues.

Steps to check or reproduce

My code is actually rather simple & a quick demo of the issue is here:

Please note, something in the the Stackblitz config seems to have mostly not want to render the page on the very first time depending on the browser. I found that if you add a space to the Comment on line 31, it will re-render everything and then the grid will be working... But this issue afaik, is a Stack Blitz issue, not a infinitegrid issue.

You can filter to "game" then delete the whole word, and you will see the grid only displays a portion of the items...


Is there some way to force the grid to complete reset itself, I've tried renderItems, updateItems, setting the array to 0 items and then back to the 600 items in a setTimeout. Changing most of the settings like useResize/isEqual/isConstant, I don't see any way to actually cause the grid to fully reset it self after I have given it a filtered dataset of less items...

daybrush commented 1 year ago

@NathanaelA okay. I'll check it.

daybrush commented 1 year ago

@NathanaelA

test svelte-infinitegrid@4.9.0-beta.5

The list will be calculated correctly.

NathanaelA commented 1 year ago

@daybrush - 4.9.0-beta.5 now gives me this error:

Uncaught TypeError: this.itemRenderer.updateItemsWithEqualSize is not a function
    at __proto._updateItems (GroupManager.ts:415:23)
    at Grid.ts:363:12
    at Component.ts:93:9
    at Array.forEach (<anonymous>)
    at __proto.trigger (Component.ts:92:16)
    at __proto.onPreReady (ImReadyManager.ts:348:10)
    at ImReadyManager.ts:79:28
    at Component.ts:98:16
    at Array.forEach (<anonymous>)
    at __proto.trigger (Component.ts:96:16)

And of course it doesn't render anything now...

NathanaelA commented 1 year ago

I believe this code is supposed to be updateEqualSizeItems not updateItemsWithEqualSize but I'm still looking at the PR's you made to see what changes were done.... As UpdateEqualSizeItems is the new function name on the Grid / ItemRenderer class...


Follow up Status: This is really weird, SOME of the dist/js files have the old name in them (but none of the TS files do), and some have them have the new name. It is almost like the name was changed mid-compile. No idea how that would have happened... But, since the actual functions in the JS match the TS code, I manually changed all them in the dist/js code...

Fortunately, manually fixing all the dist/js code so that all places that says updateItemsWithEqualSize to be named updateEqualSizeItems does fix the above error and the grid starts displaying again.

However the issue with missing items is still present, I'm still seeing this.

image

Where that scroll bar can scroll about 20 pages down because it knows there is 680 items -- but it is only showing 50 of them.

I do have on:

   isEqualSize="true"
   isConstantSize="true"

as each item is the exact same height and width as every other item and hard coded in the css....

Doing some more tests if I remove the isConstantSize="true" this does seems to fix the grid issue. So something with the isConstantSize code appears to be messing something up...

daybrush commented 1 year ago

@NathanaelA

I missed it because I was testing multiple PRs.

Test @egjs/svelte-infinitegrid@4.9.0-beta.7

https://github.com/naver/egjs-infinitegrid/pull/531

NathanaelA commented 1 year ago

@daybrush - 4.9.0-beta.7 does fix the Uncaught TypeError: this.itemRenderer.updateItemsWithEqualSize is not a function error -- so that is awesome!

However I am still seeing the grid missing items that this bug is about.

image

Unfortunately, I was wrong about isContantSize causing the issue. After duplicating it with both isContantSize and isEqualSize I removed each one in turn and finally have both removed and I can still duplicate the problem fairly easily.

Basically, I type "zero", backspace once, let it redraw, backspace a second time let it redraw and scroll the list (everything is still their), then delete another character scroll the list, select all and delete the "z" and let it redraw. On this redraw it appears to only have the same number of items that it did when it was set to "z", and as the picture shows above has probably 25 lines of blank items.

I updated the example: https://stackblitz.com/edit/sveltejs-kit-template-default-dfktlz?file=src/routes/+page.svelte

To include several "ze" named items so that you can follow the instructions I just did and to use the beta-7 version of the library. Let me know if you need anything else....

daybrush commented 1 year ago

@NathanaelA

Could you try adding that prop scrollContainer=".assetContainer"?

NathanaelA commented 1 year ago

@daybrush - This seems to fix the Demo, but does nothing for my actual project, which is very weird since I've duplicates the css and classes fairly well. I am still seeing this in my live app.

Do you have any suggestions on how I can debug this.

daybrush commented 1 year ago

@NathanaelA

I also couldn't find a solution to this, but I'm looking for a way to change the scoped class name in svelte.

<MasonryInfiniteGrid
          bind:this={ig}
            align="start"
            class="assetContainer" />

So, in css, you have to use it as a global class name.

:global(.assetContainer) {
    display: block;
    background-color: grey;
    color: white;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    user-select: none;
    padding: 1px 2px 1px 2px;
    width: 100%;
}

.container {
  overflow: hidden auto;
  position: fixed;
  top: 120px;
  bottom: 30px;
  left: 35px;
  right: 0px;
}
NathanaelA commented 1 year ago

Well, I'm still seeing this issue on my project, however it does appear that doing a setTimeout( () => { ig.updateItems(); }, 250); will at least cause it to fix it...

Is updateItems or renderItems() a better choice for forcing it to redraw everything?

I hate having to use hacks, but at least the hack now seems to work (Unless their is a better way to completely reset the grid?)

Any thoughts on what I can do to debug why it fails every time after typing "zero" <backspace>, <backspace>, <backspace>, <backspace>. At this point the grid does what my original issue in my app. However, I can't make the demo fail, not sure if it just isn't as heavy or something timing related is creating the issue. The CSS appears to be 100% identical, and the layout appears to be now equivalent.

(On the Scoped CSS, that isn't a big issue, that is a fairly common practice...)

daybrush commented 1 year ago

.updateItems(), or .renderItems({ useResize: true })

but if you use isConstantSize, Use .renderItems({ useOrgResize: true }).

NathanaelA commented 1 year ago

Just an interesting note; I updated to the latest version today and couldn't duplicate the issue and was a bit confused. So I counted the number of columns I had in the original issue and found that "13" seems to have caused the issue. I then experimented with everything 3 columns and above and found some weird behavior. Issue occurs with (684 Items in my list):
Typing "Zero" then backspace once, scrolling to the bottom, repeat

Always Broken: 3 (2 used), 5 (4 used), 7 (3 used), 8 (4 used), 9 (2 used), 13 (8 used) Always Worked: 10 (4 used), 11 (10 used), 12 (8 used), 14 (10 used), 15 (14 used), 16 (4 used) Randomly Failed: 4 (all 4 used), 6 (2 used),

So basically it is the number of columns shown, how many were used on the last line when we backspaced to the letter "z" from "zero" and then finally removed the last "z". Some sizes always work, some sizes always failed.

I tried updating the demo above, but no matter what I do on it, it works on it fine always, I suspect it is some weird sort of timing issues as my code has different images for every single icon that is loaded/cached from a remote site.