lottie-react-native: Lottie animation doesn't play after Expo upgrade.

Description

I’m using React Native with Expo. Today I upgraded expo from version 42.0.0 to version 44.0.0(last), and I noticed that my lottie animations doesn’t play on iOS and Android. However if I change speed from current to another animation starts to work as expected. autoPlay param set to true.

Steps to Reproduce

  1. Use expo version ^44.0.0
  2. Use lottie-react-native version 5.0.1
  3. Use this code:
<LottieView
                      loop={true}
                      speed={1}
                      style={{height: hp('35%'), alignSelf: 'center'}}
                      autoPlay={true}
                      source={require('./../../../assets/lottie/noPlacesInProfile.json')}
                      renderMode={"SOFTWARE"}
         />

Expected behavior: Animation plays

Actual behavior: Animation doesn’t play until I change speed param.

Versions

{ npm: ‘6.14.13’, ares: ‘1.17.1’, brotli: ‘1.0.9’, cldr: ‘38.1’, icu: ‘68.2’, llhttp: ‘2.1.3’, modules: ‘83’, napi: ‘8’, nghttp2: ‘1.42.0’, node: ‘14.17.0’, openssl: ‘1.1.1k’, tz: ‘2020d’, unicode: ‘13.0’, uv: ‘1.41.0’, v8: ‘8.4.371.23-node.63’, zlib: ‘1.2.11’ expo version ^44.0.0 lottie-react-native version 5.0.1 }

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 10
  • Comments: 33 (6 by maintainers)

Most upvoted comments

We are also experiencing this issue. autoPlay property no longer starts the animation. We also upgraded from 42 -> 44 sdk.

Temp Workaround:

const lottieRef = useRef<AnimatedLottieView|null>(null);

useEffect(() => {
  if (lottieRef.current) {
    setTimeout(() => {
      lottieRef.current?.reset();
      lottieRef.current?.play();
    }, 100);
  }
}, [lottieRef.current]);

...

<LottieView
    ref={lottieRef}
    loop={true}
    speed={1}
    style={{height: hp('35%'), alignSelf: 'center'}}
    source={require('./../../../assets/lottie/noPlacesInProfile.json')}
    renderMode={"SOFTWARE"}
/>

Hope this helps and looking forward to a fix.

I faced the same issue and I found a workaround that should work. The thing is ref is attached after first rendering, so we need to call ref.current 1 tick later.

const lottieRef = useRef<AnimatedLottieView>(null);

useEffect(() => {
    setTimeout(() => {
      if (lottieRef.current) {
        lottieRef.current.play();
       }
    }, 1);
}, []);

...

<LottieView
    ref={lottieRef}
   ...
/>

Just wanted to chip in that I’m having the same issue and some of the solutions above were not working consistently for me but this however is consistently working for me as a workaround, the animations are always playing now:

import React from 'react';

import LottieView from 'lottie-react-native';

const LottieAnimation = () => {
  const lottieRef = React.useRef<LottieView | null>(null);

  React.useEffect(() => {
    if (lottieRef.current) {
      lottieRef.current.play();
    }
  }, [lottieRef.current]);

  return <LottieView ref={lottieRef} source={require('../../assets/my_asset.json')} />;
};

export default LottieAnimation;

EDIT: Actually - this turned out be inconsistent as well! Ended up with this mix of solutions in this thread:

const LottieAnimation = ({ source, style, loop = true, autoPlay = true }: Props) => {
  const lottieRef = React.useRef<LottieView | null>(null);
  const [lottieSpeed, setLottieSpeed] = React.useState<number>(1);

  React.useEffect(() => {
    setLottieSpeed(0.9);

    if (lottieRef.current) {
      lottieRef.current.play();
      setTimeout(() => {
        setLottieSpeed(1);
      }, 250);
    }
  }, [lottieRef.current]);

  return (
    <LottieView ref={lottieRef} source={source} style={style} loop={loop} autoPlay={autoPlay} speed={lottieSpeed} />
  );
};

export default LottieAnimation;

@Amaru333 This is what I’m now using, I replaced my lottie animations with a custom component with its own ref, so this should work for you.

import React, {useEffect, useRef} from 'react';
import AnimatedLottieView from "lottie-react-native";

function Animation({source, style, onAnimationFinish, autoplay = true, loop = true, speed = 1.5}) {
    // temp ios fix begin
    // @see https://github.com/lottie-react-native/lottie-react-native/issues/832
    const lottieRef = useRef(null);
    useEffect(() => {
        lottieRef.current?.reset();
        setTimeout(() => {
            lottieRef.current?.play();
        }, 0)

    }, []);
    // fix end

    return(
        <AnimatedLottieView
            source={source}
            autoPlay={autoplay}
            loop={loop}
            style={style}
            speed={speed}
            onAnimationFinish={onAnimationFinish}
            ref={lottieRef}
        />
    );
}

My workaround:

    const anim = useRef(null);

    useEffect(() => {
        setTimeout(() => {
            anim.current.play();
        }, 0)
    }, [])

Just calling setTimeout function takes enough time as @taneba said.

I would need to get access to a repo in which this is happening as I couldn’t reproduce in any of my tests.

@tarasvakulka not required but recommended. Previous versions may or may not work

@emilioicai Repo with reproducible demo app -> https://github.com/tarasvakulka/lottie-example-app There are two ways to reproduce:

  1. Just move app to background and open from background again - animation does not autoplay. For comparing, on “lottie-react-native”: “4.1.3” this bug doesn’t appear.
  2. Build release .ipa and open it on IPhone 12 Pro Max IOS 15.5, immediately after app launch you can see that autoplay doesn’t work, because animation doesn’t play (I also tested on IPhone X and this way doesn’t work for it, only first one with move to background and reopen).

None of the above workarounds worked for me, but this mish-mash combining answers from @jerearaujo03 and @salmanExpo did.

    // temp lottie fix begin
    // @see https://github.com/lottie-react-native/lottie-react-native/issues/832
    const lottieRef = useRef(null);
    useEffect(() => {
        lottieRef.current?.reset();
        setTimeout(() => {
            lottieRef.current?.play();
        }, 100)

    }, []);
    // fix end

@emilioicai Did my repo with example help you to reproduce the bug ? Or may be would be better to create new issue for that ?

Hmm, interesting. If I create a completely new Expo app the autoPlay work as intended 🤔

  1. npx expo-cli@latest init .
  2. npx expo-cli@latest add lottie-react-native
  3. Add a Lottie animation to assets folder, e.g. countdown_10.json
  4. Replace app.js with:
    import { StatusBar } from 'expo-status-bar';
    import LottieView from 'lottie-react-native';
    import { StyleSheet, View } from 'react-native';
    
    export default function App() {
      return (
        <View style={styles.container}>
          <StatusBar style="auto" />
    
          <LottieView
            autoPlay
            loop
            style={{ width: 200, height: 200 }}
            source={require('./assets/countdown_10.json')}
          />
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: '#666',
        alignItems: 'center',
        justifyContent: 'center',
      },
    });
    
  5. npx expo-cli@latest start
  6. Scan QR on phone and test out

Ref values shouldn’t be used as dependencies to useState as changing the useRef current value won’t trigger an update.

We are using this workaround currently:

const lottieRef = useCallback((node: LottieView | null | undefined) => node?.play(), [])

// ...

<LottieView
    ref={lottieRef}
    // ...
/>