I'm getting started with react-native with expo and typescript. Currently trying to implement a Video-Playback component into my app.
I'm following the example in the official docs and a youtube video, which uses almost exactly the same example code.
I had to make some modifications to the code to satisfy typescript (see comments):
import { AVPlaybackStatus, ResizeMode, Video } from "expo-av";
import { useRef, useState } from "react";
import { Button, Text, View } from "react-native";
import { StyleSheet } from "react-native";
export default function Index() {
const video = useRef<Video>(null); // without '<Video>' I'd get a lot of errors below in the jsx
// const [status, setStatus] = useState({}); //this is how it is in both the docs & yt tutorial
const [status, setStatus] = useState({
isLooping: false,
isPlaying: false,
//...
}); //I had to initialize these values otherwise I'd get errors below ('status.isPlaying' & 'status.isLooping')
return (
<View style={styles.container}>
<Video
ref={video}
style={styles.video}
source={{
uri: 'https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
}}
useNativeControls
resizeMode={ResizeMode.CONTAIN}
isLooping
onPlaybackStatusUpdate={status => setStatus(() => status)} //exactly as in the docs, doesn't work
// onPlaybackStatusUpdate={(status: AVPlaybackStatus) => setStatus(() => status)} //also doesn't work
// onPlaybackStatusUpdate={setStatus} //also doesn't work
// onPlaybackStatusUpdate={(status: AVPlaybackStatus) {
// setStatus(status);
// }} //nothing works
/>
{/* had to add some exclamation marks to satisfy typescript */}
<View style={styles.buttons}>
<Button title="Play from 5s" onPress={() => video.current!.playFromPositionAsync(5000)}/>
<Button title={status.isLooping ? "Set to not loop": "Set to loop"} onPress={()=>video.current!.setIsLoopingAsync(!status.isLooping)}/>
<Button
title={status.isPlaying ? 'Pause' : 'Play'}
onPress={() =>
status.isPlaying ? video.current!.pauseAsync() : video.current!.playAsync()
}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
video: {
flex: 1,
alignSelf: 'stretch'
},
buttons: {
// color: 'blue',
flex: 1,
// alignSelf: 'stretch'
}
});
status
is underlined in red and I get the following error when hovering over it:
Argument of type '() => AVPlaybackStatus' is not assignable to parameter of type 'SetStateAction<{ isLooping: boolean; isPlaying: boolean; }>'.
Type '() => AVPlaybackStatus' is not assignable to type '(prevState: { isLooping: boolean; isPlaying: boolean; }) => { isLooping: boolean; isPlaying: boolean; }'.
Type 'AVPlaybackStatus' is not assignable to type '{ isLooping: boolean; isPlaying: boolean; }'.
Type 'AVPlaybackStatusError' is missing the following properties from type '{ isLooping: boolean; isPlaying: boolean; }': isLooping, isPlayingts(2345)
I think you have to simply change
const [status, setStatus] = useState({
isLooping: false,
isPlaying: false,
//...
})
to
const [status, setStatus] = useState<AVPlaybackStatus>()