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

Workarounds to prevent known issue of array change glitching? #195

Open
zxol opened this issue Nov 5, 2017 · 5 comments
Open

Workarounds to prevent known issue of array change glitching? #195

zxol opened this issue Nov 5, 2017 · 5 comments

Comments

@zxol
Copy link

zxol commented Nov 5, 2017

Thanks for a great library!

In my use case, I am using FlipMove to animate a list of items up to 100 items that can be filtered down to none instantly or filtered differently, in rapid succession . As documented, this causes some weird glitches with FlipMove.

Is there anything I can do avoid this? Perhaps updating the array batchwise, with a small delay between groups? Or even delay each array update? I'm guessing that will cause a ton more render calls, would that be right?

@joshwcomeau
Copy link
Owner

Hey there, sorry for the delay!

Yeah, so interrupts (especially when interrupts involve items being added/removed) are a very hard problem that we haven't been able to solve yet. It's something I wish I had a better answer for, but I suspect a proper fix would involve a teardown/rebuild with WAAPI, which introduces a bunch of its own issues (like very poor browser support without a hefty polyfill).

The safest approach has some unpleasant UX side-effects: if you disable the filtering while a filter is in progress, you remove the complexity of interrupts. So if your transition length is 500ms, just disable the filter options for 500ms, grey them out in the UI.

You could try the approaches you listed (like updating in batches) but I'm not hopeful about that solution. I don't know if I understand what you mean by "delay each array update", maybe you're talking about the same thing I am, with disabling interrupts? If so, I don't believe it would cause unnecessary renders - FlipMove will render every time it receives new props.

Hope it helps! Let me know what you wound up doing :)

@ggregoire
Copy link

Using leaveAnimation={null} fixed it for me.

Full code:

      ...
        <tbody>
          <FlipMove
            duration={300}
            easing="ease-out"
            enterAnimation="fade"
            leaveAnimation={null}
            typeName={null}
          >
            {sortBy(items, sortPredicate).map(item => (
              <tr key={item.id} id={item.id} onClick={this.handleClick}>
                ...

@mrlubos
Copy link

mrlubos commented Mar 4, 2018

@ggregoire How did you come up with that! I've been struggling with duplicate elements forever, this works like a charm.

@shaunsaker
Copy link

@ggregoire Typesafe equivalent is to use leaveAnimation='none'.

@keegan-lillo
Copy link

For posterity: There is another way to guard against this if you do want a leaveAnimation. If you add an onStartAll callback to check if the number of domNodes is unexpected, you can remount the <FlipMove> component by updating a key prop on it.

Example:

function Foo({ someList }) {
  const [overloadCounter, setOverloadCounter] = useState(1)
  const overloadTimoutRef = useRef(-1)
  const duration = 500

  // clean up the timer
  useEffect(() => () => clearTimeout(overloadTimoutRef.current))

  return (
    <FlipMove
      key={overloadCounter}
      duration={duration}
      onStartAll={(childElements, domNodes) => {
        const numDomNodes = domNodes.length
        clearTimeout(overloadTimoutRef.current)

        // check after the duration has elapsed if we have an unexpected number of DOM nodes
        overloadTimoutRef.current = window.setTimeout(() => {
          if (numDomNodes > someList.length) {
            setOverloadCounter(overloadCounter + 1)
          }
        }, duration)
      }}
    >
      {someList.map(({ id, content }) => (
        <div key={id}>{content}</div>
      ))}
    </FlipMove>
  )
}

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

6 participants