nandorojo / moti

🐼 The React Native (+ Web) animation library, powered by Reanimated 3.
https://moti.fyi
MIT License
3.9k stars 120 forks source link

Sequences get out of sync #287

Closed d4rky-pl closed 1 year ago

d4rky-pl commented 1 year ago

Is there an existing issue for this?

Current Behavior

This is just my theory for now as I did not manage to create a repro but it seems that if the CPU thread gets busy during animation, the animations can sometimes get out of sync or finish too early and are then broken on all subsequent transitions. This seems to happen both with animate prop and with hooks.

In my case it was a screen with multiple List.Item from react-native-paper and the rendering happened in react-navigation tab bar but I'm still trying to narrow it down for a repro.

Expected Behavior

The sequence animations should always work in a predictable manner

Steps To Reproduce

  1. Animate multiple properties either with animate prop or useDynamicAnimation hook. Make sure the animation duration is short (in my case duration: 75) or the issue will not trigger.
  2. Run the animation while triggering an expensive render of UI

Versions

- Moti: 0.25.3, 0.24.2
- Reanimated: 2.14.4
- React Native: 0.71.7
- Expo SDK 48.0.16

Screenshots

In demo below, clicking on the servers icon (which renders a react-navigation tab with more content) triggers the glitch:

https://github.com/nandorojo/moti/assets/284395/0225a92e-b149-478c-9019-8ff34211784b

The demo was recorded on latest moti with #286 but I can confirm the problem also happens on 0.24.2

Reproduction

I'm still working on repro as I can't seem to be able to isolate the problem during the weekend. I will try to provide it in the coming days. I'm creating this issues just to flag that the problem is there in case you're able to reproduce it on your end.

The animation was defined like this:

// Indicator is MotiView wrapped with styled-components for extra styles
<Indicator
  from={{
    left: getDotPosition(previousIndex.current),
    backgroundColor: getDotColor(previousIndex.current),
  }}
  animate={{
    left: getDotPosition(state.index),
    backgroundColor: getDotColor(state.index),
    scale: [0.25, 1],
  }}
  transition={{ type: "timing", duration: 75 }}
/>
// The component that caused the UI thread to be expensive

// This came from API but replacing it with static object made no difference for the bug
const instances = [
  { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" },
  { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" },
  { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" }, { name: "abc" },
];

// Container is just View with flex: 1 and background, List.Item comes from react-native-paper
return (
  <Container>
    {instances.map((instance) => (
      <List.Item
        title={instance.name}
        description={"Available for reservation"}
        key={instance.name}
      />
    ))}
  </Container>
);
nandorojo commented 1 year ago

sorry i don’t exactly get the issue (or where moti comes in)

react navigation is historically very slow when toggling tabs. it’s hard to navigate when it does

consider firing the animation after a navigation change event

sannajammeh commented 1 year ago

For me, Sequences just stop working.

nandorojo commented 1 year ago

Can you open a new issue with a reproduction? I don’t know how to address this one.

For what it’s worth, it’s useful to wrap components in useMemo. Maybe Reanimated 3 helps too.