Search code examples
javascriptreactjsexpojsxexpo-av

Expo AV: 'if' video has finished, go back to start


I am trying to create a function in Expo AV where 'if' the video has finished playing, it automatically returns to the start. The restart() function that I created does not allow this. Please excuse me as I am quite new to this! This is my code:

export default function App() {
  const video = React.useRef(null);
  const [status, setStatus] = React.useState({});

  const restart = () => {
    if (video.status.didJustFinish) {
      video.current.playFromPositionAsync(0);
    }
  };

  restart();

  return (
    <View style={styles.container}>
      <Video
        ref={video}
        style={styles.video}
        source={require("./assets/big_buck_bunny.mp4")}
        useNativeControls={false}
        volume={1.0}
        resizeMode={ResizeMode.CONTAIN}
        isLooping={false}
        onPlaybackStatusUpdate={status => setStatus(() => status)}
      />
      <View style={styles.buttons}>
        <TouchableOpacity onPress={() => status.isPlaying ? video.current.pauseAsync() : video.current.playAsync()}>
          {status.isPlaying ? (
            <>
              <AntDesign style={styles.icons} name="pause" size={50} color="white" />
            </>
          ) : (
            <>
              <AntDesign style={styles.icons} name="play" size={50} color="white" />
            </>
          )}
        </TouchableOpacity>
      </View>
    </View >
  );
}

Solution

  • Wrap the logic of your restart function in a useEffect hook and add status as the dependency to observe. Whenever status changes, the effect will run and start the video from the start if didJustFinish is true.

    export default function App() {
      const video = React.useRef(null);
      const [status, setStatus] = React.useState({});
    
      useEffect(() => {
        if (status?.didJustFinish) {
          video.current.playFromPositionAsync(0);
        }
      }, [status]);
    
      return (
        <View style={styles.container}>
          <Video
            ref={video}
            style={styles.video}
            source={require("./assets/big_buck_bunny.mp4")}
            useNativeControls={false}
            volume={1.0}
            resizeMode={ResizeMode.CONTAIN}
            isLooping={false}
            onPlaybackStatusUpdate={status => setStatus(status)}
          />
          <View style={styles.buttons}>
            <TouchableOpacity onPress={() => status.isPlaying ? video.current.pauseAsync() : video.current.playAsync()}>
              {status.isPlaying ? (
                <>
                  <AntDesign style={styles.icons} name="pause" size={50} color="white" />
                </>
              ) : (
                <>
                  <AntDesign style={styles.icons} name="play" size={50} color="white" />
                </>
              )}
            </TouchableOpacity>
          </View>
        </View >
      );
    }