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

Feature Request: Virtualisation #68

Open
robwheatley opened this issue Jan 29, 2021 · 1 comment
Open

Feature Request: Virtualisation #68

robwheatley opened this issue Jan 29, 2021 · 1 comment

Comments

@robwheatley
Copy link

robwheatley commented Jan 29, 2021

Hi there,

I've run into a bit of an issue with my app when it comes to longer lists - horrible lag! Nothing to do with react-sortly, it's just that the list I'm rendering has some quite heavy items in it.

I was wondering if you could add some virtualisation to Sortly?

I've had a play with virtualising my list (Virtuoso) and it makes my longer lists that were taking 2seconds to mount/dismount as good as instant!

Unfortunately, I can't get Sortly and Virtuoso to play nice together, so in my tests, I removed Sortly. But if virtualisation could be built-in, this would be a massive improvement.

Any thoughts?

@robwheatley
Copy link
Author

An update on this. I can kind of get virtualisation to work. On the face of it, it looks fine, but I do get some strange behaviour in certain circumstances, and I would really appreciate some guidance to help me fix the issue.

First up, this is how I got Virtuoso into Sortly...

In Sortly.tsx, I replaced these lines that render the items:

    <sortlyContext.Provider value={{ items }}>
      {items.map((data, index) => (
        <itemContext.Provider 
          key={data.id} 
          value={{
            index,
            id: data.id, 
            type, 
            depth: data.depth,
            data,
            onHoverBegin: handleHoverBegin,
            onHoverEnd: handleHoverEnd,
          }}
        >
          <Item<D>
            index={index}
            id={data.id}
            depth={data.depth}
            data={data}
          >
            {children}
          </Item>
        </itemContext.Provider>
      ))}
    </sortlyContext.Provider>

With these, that render via Virtuoso

      <sortlyContext.Provider value={{ items }}>
        <Virtuoso
          totalCount={items.length}
          style={{height:'200px', width:'100%'}}
          itemContent={(index) => {
            const data = items[index]
            return (
              <itemContext.Provider
                key={data.id}
                value={{
                  index,
                  id: data.id,
                  type,
                  depth: data.depth,
                  data,
                  onHoverBegin: handleHoverBegin,
                  onHoverEnd: handleHoverEnd,
                }}
              >
                <Item
                  index={index}
                  id={data.id}
                  depth={data.depth}
                  data={data}
                >
                  {children}
                </Item>
              </itemContext.Provider>
          )}}
        />
      </sortlyContext.Provider>

Once that is done, I get a super speedy list, and everything seemed to be working fine. But there is one major problem.

There seems to be a 'ghost' process with old state data in, that is causing a loop. I guess something didn't update due to virtualisation.

A great example is a depth change. If you make an allowed depth change, the change works fine (the onChange prop fires to tell the parent about the change, which updates all the states fine). If, in a single drag event, you make 2 changes (e.g. move from 0 to 1 and then to 2) this also works.

The problem arises if, in a single drag, you make at least 1 depth change, but then go on to try a 'disallowed' change. e.g, you have a max depth of 1 and you drag from 0 to 1 then try to move to 2. Or, you try and increase the depth to be >1 more than the parent.

In this case, Sortly thinks there is a change to make because its items array actually has the original items in (from the start of the drag). In other words, they didnt get updated after the 1st successful change.

It's not as simple as that though. It looks as if there are 2 callbacks happening. One with the 'real' items in (which doesn't trigger an onChange as you would expect) and one with the old items in (which is what is causing the problem). They both trigger at the same time (+/1 a millisecond or 2). This second event does not occur if you back out the Virtuoso code. The problem is that this 'ghost' change tells the parent to update state and you get stuck in a loop until the user either stops dragging or moves the drag item back into an allowed position.

I'm hoping that to fix this, it's just a simple case of calling Virtuoso differently in the code I added to Sortly.

I'd love a bit of guidance on this if you can spare the time...

Rob.

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

No branches or pull requests

1 participant