react-native-video-controls
react-native-video-controls copied to clipboard
Render Error [2209, "RCTVIEW",{"width":"<<NaN>>"}] is not usable as a native method argument
When using the Video component from react-native-video-controls, I get this error. With the Video component from react-native-video, it works perfectly. I also have found that if I leave the controls
enabled for the native controls, the error doesn't happen. Is there something I'm doing wrong?
My Base player:
import React, { ReactPropTypes, SetStateAction, useCallback, useState } from 'react';
import Video1, { VideoProperties } from 'react-native-video';
import Video from 'react-native-video-controls';
import { Animated, StyleSheet, Text, View } from 'react-native';
import { Image } from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import { colors } from '../styles/colorPalette';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { useTheme } from '../contexts/ThemeContext';
import { ReactNativeProps } from 'react-native-render-html';
interface VideoPlayerProps extends VideoProperties {
autoPlay?: boolean
categoryOverlay?: boolean | string
ref?: any
}
const VideoPlayer = (props: VideoPlayerProps & ReactNativeProps) => {
const [vidAspectRatio, setVidAspectRatio] = useState(1.8)
const [duration, setDuration] = useState(null);
const [progress, setProgress] = useState(1);
const [isPlaying, setIsPlaying] = useState(!props.paused || false);
const [controlsActive, setControlsActive] = useState(false);
const { darkMode } = useTheme();
const { categoryOverlay } = props;
const handleHeight = (res: any) => {
// set height and duration
setDuration && setDuration(res?.duration);
setVidAspectRatio(res?.naturalSize?.width / res?.naturalSize?.height || 1.8);
}
const handlePause = (res: any) => {
// The logic to handle the pause/play logic
res.playbackRate === 0 ? setIsPlaying(false) : setIsPlaying(true);
}
const handleProgress = (progress: any) => {
setProgress(progress.atValue);
}
const styles = StyleSheet.create({
container: {
position: 'relative',
resizeMode: 'cover',
aspectRatio: vidAspectRatio,
justifyContent: 'center',
alignItems: 'center',
},
playIcon: {
color: darkMode ? colors.primary.purple4 : "#fff",
fontSize: 30,
},
playIconContainer: {
backgroundColor: darkMode ? '#fff' : colors.primary.purple4,
paddingHorizontal: 15,
paddingVertical: 7.5,
borderRadius: 10,
},
video: {
flex: 1,
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
},
videoPoster: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
resizeMode: 'cover',
},
categoryOverlay: {
paddingHorizontal: 10,
paddingVertical: 5,
position: 'absolute',
color: '#fff',
bottom: 10,
right: 10,
backgroundColor: 'rgba(0,0,0, .75)',
borderRadius: 10,
zIndex: 999,
textTransform: 'uppercase',
},
});
const convertTime = (seconds: number) => {
const secsRemaining = Math.floor(seconds % 60);
return `${Math.floor(seconds / 60)}:${secsRemaining < 10 ? '0' + secsRemaining : secsRemaining}`
}
const convertTimeV2 = (secs: number) => {
var hours = Math.floor(secs / 3600)
var minutes = Math.floor(secs / 60) % 60
var seconds = Math.floor(secs % 60)
return [hours,minutes,seconds]
.map(v => v < 10 ? "0" + v : v)
.filter((v,i) => v !== "00" || i > 0)
.join(":")
}
return (
<View style={styles.container}>
<Video
{...props}
/* controls */
disableBack
disableFullscreen
disablePlayPause
paused={!isPlaying}
onLoad={handleHeight}
onHideControls={() => setControlsActive(false)}
onShowControls={() => setControlsActive(true)}
onPlaybackRateChange={handlePause}
onProgress={handleProgress}
style={styles.video}
videoStyle={styles.video}
seekColor="#a146b7"
controlTimeout={3000}
tapAnywhereToPause
/>
{categoryOverlay && progress === 1 &&
<View style={styles.categoryOverlay}>
<Text style={{color: "#fff", textTransform: 'uppercase'}}>{(typeof categoryOverlay === 'boolean') && duration ? convertTime(duration) : categoryOverlay}</Text>
</View>
}
{ (progress === 1 && !isPlaying) && <View style={styles.videoPoster}><Image style={{width: '100%', height: '100%', resizeMode: 'cover'}} source={{ uri: props.poster }} /></View> }
{ (!isPlaying || controlsActive) &&
<Animated.View style={styles.playIconContainer}>
<TouchableOpacity onPress={() => isPlaying ? setIsPlaying(false) : setIsPlaying(true)}>
<Icon style={styles.playIcon} name={isPlaying ? "pause" : "play"} />
</TouchableOpacity>
</Animated.View> }
</View>
);
}
export default VideoPlayer
My live video player:
import React, { useCallback, useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import VideoPlayer from './VideoPlayer';
import Icon from 'react-native-vector-icons/FontAwesome';
import { colors } from '../styles/colorPalette';
import PeopleCard from '../components/PeopleCard';
import { useTheme } from '../contexts/ThemeContext'
export default function LiveVideoCard(props: any) {
const { darkMode } = useTheme();
const [link, setLink] = useState<LiveVideoResponse | null>(null)
const [loading, setLoading] = useState(true)
interface LiveVideoResponse {
poster: string
title: string
url: string
}
const styles = StyleSheet.create({
container: {
backgroundColor: darkMode ? colors.background.darkBg : '#fff',
flex: 1,
padding: 20,
borderTopWidth: 1,
borderBottomWidth: 1,
borderStyle: 'solid',
borderColor: 'rgba(0,0,0,0.25)',
},
inner: {
backgroundColor: darkMode ? colors.surface.dark1 : '#fff',
borderWidth: 1,
borderColor: darkMode ? 'rgba(255,255,255,0.25)' : 'rgba(0,0,0,0.25)',
borderRadius: 20,
paddingVertical: 20,
},
title: {
fontWeight: 'bold',
fontSize: 16,
color: darkMode ? '#fff' : colors.primary.purple4,
marginBottom: 10,
},
body: {
color: darkMode ? '#efefef' : 'black'
},
})
const getLink = useCallback(async () => {
try {
const data = await fetch('https://test.com/config_live_stream/get_live_stream', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'test': 'test'
},
})
const json = await data.json()
setLink(json.data[0])
} catch(e) {
console.error(e)
}
finally {
setLoading(false)
}
}, [link])
useEffect(() => {
getLink();
}, [])
return (
!loading && link ?
<View style={styles.container}>
<Text style={{color: darkMode ? '#fff' : 'black', fontFamily: "Sequel 100 Wide 65", fontSize: 13, marginBottom: 20, paddingHorizontal: 10}} ><Icon name="circle" size={10} style={{paddingLeft:5, color:"#e32525"}} /> Live now</Text>
<View style={styles.inner}>
<PeopleCard data={{ image_url: link.poster, title: 'test', }} />
<VideoPlayer paused={false} muted={true} source={{ uri: link.url }} />
<View style={{padding: 20}}>
<Text style={styles.title}>{link.title}</Text>
</View>
</View>
</View>
: null
)
}
The error in Metro:
Error: Exception in HostFunction: Malformed calls from JS: field sizes are different.
[[73,50,50,3],[0,6,6,3],[[66,0,1639731698612,false],[1]],3174]
This error is located at:
in PanGestureHandler (at GestureHandlerNative.tsx:14)
in PanGestureHandler (at Drawer.tsx:532)
in DrawerView (at DrawerView.tsx:273)
in DrawerViewBase (at DrawerView.tsx:317)
in RCTView (at View.js:32)
in View (at DrawerView.tsx:316)
in RCTView (at View.js:32)
in View (at SafeAreaProviderCompat.tsx:42)
in SafeAreaProviderCompat (at DrawerView.tsx:315)
in DrawerView (at createDrawerNavigator.tsx:126)
in Unknown (at createDrawerNavigator.tsx:125)
in DrawerNavigator (at App.tsx:47)
in EnsureSingleNavigator (at BaseNavigationContainer.tsx:430)
in BaseNavigationContainer (at NavigationContainer.tsx:132)
in ThemeProvider (at NavigationContainer.tsx:131)
in NavigationContainerInner (at App.tsx:45)
in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
in SafeAreaProvider (at App.tsx:44)
in CustomApp (at App.tsx:82)
in ThemeContextProvider (at App.tsx:81)
in App (at renderApplication.js:50)
in RCTView (at View.js:32)
in View (at AppContainer.js:92)
in RCTView (at View.js:32)
in View (at AppContainer.js:119)
in AppContainer (at renderApplication.js:43)
in testmobile(RootComponent) (at renderApplication.js:60), js engine: hermes
Same problem ,
What version are you using? I'm encountering similar issues with [email protected]
, react-native-video@^6.0.0-alpha.1
, react-native-video-controls@^2.8.1
Same for me too.... Any solution ???
In my case the crash was due to using react-native-gesture-handler
on a specific app page (the same where the video component was*). After removing usages of react-native-gesture-handler
in that page and switching previous logic to React Native's gesture system, the page worked fine without crashing.
*I'm not using react-native-video-controls
directly, but its dependency react-native-video
(i needed my own custom video controls UI) but the issue is still relevant.
I fixed this problems with
import { Dimensions } from "react-native";
// ...
// render() component
<VideoPlayer style={{
left: 0,
top: 0,
bottom: 0,
right: 0,
width: Dimensions.get('window').width,
height: 2160 * (Dimensions.get('window').width / 3840)
}} source={{ uri: "https://www.google.com/google.mp4" }}
/>
// this will fit your player to 16:9 aspect ratio
I had to patch the package to replace
const percent = this.state.currentTime / this.state.duration;
with
const percent = this.state.duration === 0 ? 0 : this.state.currentTime / this.state.duration;
in VideoPlayer.js since it doesn't look like they're merging any PRs recently
Now i know this error only occurred in DEBUG mode. I fixed it by briefly pressing the pause button, then waiting for the video to finish loading and then pressing the play button.
I had to patch the package to replace
const percent = this.state.currentTime / this.state.duration;
withconst percent = this.state.duration === 0 ? 0 : this.state.currentTime / this.state.duration;
in VideoPlayer.js since it doesn't look like they're merging any PRs recently
This is working, can we raise and merge PR ???
I had to patch the package to replace const percent = this.state.currentTime / this.state.duration; with const percent = this.state.duration === 0 ? 0 : this.state.currentTime / this.state.duration; in VideoPlayer.js since it doesn't look like they're merging any PRs recently
This is working! Thanks!