How to continue a video between Screens with StackNavigation in React Native? - reactjs

Hey Everyone I'm trying to use a video as a Background for several screens but the problem is when I'm trying to re use the BackgroundVideo.js in an another screen, the video would stop and replay at the begin when i'm switching between Screen (Lauchscreen to the SignInScreen).
I want to make this continue and not that the video replay.
An idea please ?
Thank you
BackgroundVideo.js :
import React, { Component, Fragment } from 'react';
import { View, StyleSheet,Dimensions, Button, Pressable, TouchableOpacity, SafeAreaView, Text } from 'react-native';
import { Video, AVPlaybackStatus } from 'expo-av';
import { assertStatusValuesInBounds } from 'expo-av/build/AV';
const { width, height } = Dimensions.get("window");
export default class BackgroundVideo extends Component {
render() {
return (
<Video
source={require("/Users/joshuabonifond/DoneWithIt/assets/BackgroundVideo.mp4")}
rate={1.0}
isMuted={true}
resizeMode="cover"
shouldPlay
isLooping style={styles.backgroundVideoStyle}
/>
);
}
}
const styles = StyleSheet.create({
backgroundVideoStyle: {
flex : 1,
height: height,
position: "absolute",
top: 0,
left: 0,
alignItems: "stretch",
bottom: 0,
right: 0,
}
});
Launchscreen.js
import React, { Component, Fragment } from 'react';
import { View, StyleSheet,Dimensions, Button, Pressable, TouchableOpacity, SafeAreaView, Text } from 'react-native';
import { Video, AVPlaybackStatus } from 'expo-av';
import { assertStatusValuesInBounds } from 'expo-av/build/AV';
import BackgroundVideo from './BackgroundVideo.js';
const { width, height } = Dimensions.get("window");
export default class Launchscreen extends Component {
render() {
return (
<View style = {styles.container}>
<BackgroundVideo/>
<Text style = {styles.TextTitle}>
First app !
{'\n'} {'\n'}
Hello There
</Text>
Navigation.js
import { getActiveChildNavigationOptions } from 'react-navigation';
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import Launchscreen from '../Components/Launchscreen';
import SignInScreen from '../Components/SignInScreen';
const HomeScreenStackNavigator = createStackNavigator({
LaunchscreenView:{
screen: Launchscreen,
navigationOptions:{
headerShown: false,
}
},
SignInScreenView: {
screen: SignInScreen,
navigationOptions:{
headerShown: false,
}
},
})
App.js
import StatusBar from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Launchscreen from './Components/Launchscreen';
import NavigationHomeScreen from './Navigation/NavigationHomeScreen';
export default class App extends React.Component {
render(){
return (
<NavigationHomeScreen/>
);
}
}

Resolved !
Like #beingbalder said, I put my Launchscreen and my SignInView in a common Screen and then, I used this method (https://ourcodeworld.com/articles/read/409/how-to-update-parent-state-from-child-component-in-react)to return the state from the Child ("Launchscreen") to my Parent Component ("CommonViewLaunch") and change the state of the variable "isLaunch" when I press on a touchableOpacity button in the Launchscreen.
Thank you so much !

You can't do that in this way.
First of all make a common screen for Launchscreen and SignInScreen and use both of these screens as component.
inside you CommonScreen.js
<View>
<BackgroundVideo/>
{isLaunch ? <Launchscreen/>:<SignInScreenView/>}
</View>
change your isLaunch variable when you are moving from launch screen to sign in screen
Note - Make sure to add proper styling so you video appear below screen components, also remove video from both screen components.

The best answer would be https://stackoverflow.com/a/69676488/10665516.
But you can also just pass the current position of the video to the next screen videoRef.getStatusAsync(). And set the starting position of the video on the next screen using videoRef.setPositionAsync(millis)

Related

Best way to get data into screen using react navigation screens. Error using hook

I have a basic flat list of products that are getting rendered from a products array. Im using react navigation to navigate to a product detail screen but trying to think of the best way to get the active selected product so I can display the product information in the product detail page.
My Approach: I thought just use a hook to provide the active product and I tried that but for some reason I am not getting the proper state provided in the product detail page.
Getting the error: "TypeError: null is not an object (evaluating 'product.title')"
By the way for now I'm trying to avoid using redux as my school project is due tomorrow and also trying to learn hooks.
EDIT: Hmm I see now I can also use Route params. I think I would still really like to understand what is going on with my current hooks approach.
Product Card Component
import React, { useState, useEffect } from "react";
import {
View,
ImageBackground,
Text,
Pressable,
StyleSheet,
Button,
Dimensions,
ScrollView,
RefreshControl,
SafeAreaView,
Image,
FlatList,
TouchableOpacity,
} from "react-native";
import { useQuery, gql } from "#apollo/client";
import Amplify, { Auth } from "aws-amplify";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import { useNavigation, NavigationContainer } from "#react-navigation/native";
import useProduct from "../hooks/useProduct";
function ProductCard({ item }) {
const navigation = useNavigation();
const { setActiveProduct } = useProduct();
const imgUrl = "http://192.168.1.252:3000" + item.media[0].URLs.thumbnail;
const imgUrl2 = imgUrl.replace("thumbnail", "large");
return (
<TouchableOpacity
style={styles.buttonContainer}
onPress={() => {
setActiveProduct(item);
navigation.navigate("Product Detail");
}}
>
<View style={styles.view}>
<Image
style={styles.productImage}
source={{
uri: imgUrl2,
}}
/>
</View>
</TouchableOpacity>
);
}
export default ProductCard;
const styles = StyleSheet.create({
buttonContainer: {
flex: 0.5,
margin: 5,
backgroundColor: "white",
},
view: {
flex: 1,
display: "flex",
flexDirection: "column",
height: 200,
},
productImage: {
width: "100%",
height: "70%",
},
description: {
width: "100%",
height: "60%",
},
});
Product Detail Page
import React, { useState, useEffect } from "react";
import {
View,
ImageBackground,
Text,
Pressable,
StyleSheet,
Button,
Dimensions,
ScrollView,
RefreshControl,
SafeAreaView,
Image,
FlatList,
TouchableOpacity,
} from "react-native";
import useProduct from "../../hooks/useProduct";
function ProductDetailScreen() {
const { product } = useProduct();
if (!product) {
return (
<View>
<Text>{product.title}</Text>
</View>
);
}
return (
<View>
<Text>{product.title}</Text>
</View>
);
}
export default ProductDetailScreen;
useProduct hook to manage my active product state
import React, { useState } from "react";
function useProduct() {
const [product, setProduct] = useState(null);
setActiveProduct = (newProduct) => {
setProduct(newProduct);
};
return { product, setActiveProduct };
}
export default useProduct;
useProduct() returns separate state objects to both components. Try using product inside ProductCard. You will see the product updated in ProductCard component. But this product is not the same that is returned to ProductDetailScreen. Both components get separate state objects.

React Native View and Flex: 1 not working as expected

I learning React Native and I'm doing a simple View and setting the style to a container style, but nothing happens when I run the code. The View is now filling with the color read from the code. Its very starter code, just not seeing where its going wrong? When I run this, nothing in the view changes, it just white? I was expecting to see a screen of red?
import React, { useState } from 'react';
import {View, Text, StyleSheet, ScrollView} from 'react-native';
import { Input } from 'react-native-elements';
import SLSHeader from '../app-components/slsheader';
export default function Home (props) {
return (
<View styles={styles.container}>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'red'
}
});
The only place Im using it thus far is in a Navigator file... Its a switch Navigator with a Drawer Navigator...
import React from 'react';
import { createAppContainer, createSwitchNavigator} from 'react-navigation';
import { createDrawerNavigator } from 'react-navigation-drawer';
//import CustomDrawer from './CustomDrawer';
//Import Screens
import LoginScreen from '../screens/Login';
import HomeScreen from '../screens/Home';
//Drawer Screens
const DrawerScreens = {
Home: {
screen: HomeScreen,
navigationOptions:{
headerShown: false
}
}
}
const DrawerNavigator = createDrawerNavigator(DrawerScreens, {
defaultNavigationOptions: {
headerStyle: {
height: 60
}
},
//contentComponent: CustomDrawer
});
//Pre Login Screens
const PreLoginScreens = {
Login: {
screen: LoginScreen,
navigationOptions:{
headerShown: false
}
},
PostLogin: {
screen: DrawerNavigator
}
}
const PreloginNavigator = createSwitchNavigator(PreLoginScreens,{
defaultNavigationOptions: {}
});
export default createAppContainer(PreloginNavigator);
Yes, in the App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import SLSNavigator from './Navigation/SLSNavigator';
export default function App() {
return (
<SLSNavigator />
);
}

TypeError: (0, _reactNavigation.default) is not a function. React Native

I am using React Navigation Version 4 and after setting my navigations and all screens and run the code I am facing the following issue:
TypeError: (0, _reactNavigation.default) is not a function.
My Routes.Js is -
import React from 'react';
import createAppContainer from 'react-navigation';
import { createStackNavigator, HeaderBackButton } from 'react-navigation-stack';
import { Drawer } from './Drawer';
import LoginScreen from '../screens/LoginScreen';
import InitialScreen from '../screens/InitialScreen';
import LogoutScreen from '../screens/LogoutScreen';
const RootStack = createStackNavigator(
{
Drawer: {
screen: Drawer
},
LoginScreen: {
screen: LoginScreen
},
LogoutScreen: {
screen: LogoutScreen
}
InitialScreen: {
screen: InitialScreen
}
},
{
initialRouteName: 'InitialScreen',
headerMode: "none"
}
)
const App = createAppContainer(RootStack);
export default App;
and Index.js is -
import React, { Component } from 'react';
import { StyleSheet, AsyncStorage } from 'react-native';
import { Button, Text, Drawer } from 'native-base';
import App from './config/Routes';
import AppHeader from './components/Header/Header';
export default class Index extends Component {
render() {
const { globalContainer } = styles;
return (
<App
style={ globalContainer }
navigation={this.props.navigation}>
</App>
)
}
}
Any help??
It appears from the documentation that it should be a named import, not a default.
import { createAppContainer } from 'react-navigation';
Please read the docs. It's also a good first place to look when debugging.

Problem to return component from StackNavigator in react-native. Get a blank screen but cosole.log is OK

What I want to do is wrapp on the very top of my app a switch navigator named MainNavigator which redirect to a LoadingScreen who determine if user is Logged or no and navigate to AuthNavigator or AppNavigator.
AuthNavigator himself is a stackNavigator who display screens 'LoginScreen' or 'SignUpScreen'.
AppNavigator is a DrawerNavigator with multiple screens (Profile, Home...).
The problem I encouter is that the return method seems to work, because I can see the logs in my console from the 'LoginScreen' component but on the screen, the only return is a white screen.. When I call directly my 'LoginScreen' component from the LoadingScreen component by using :
_bootstrapAsync = async () => {
const userToken = await AsyncStorage.getItem('userToken');
// This will switch to the App screen or Auth screen and this loading
// screen will be unmounted and thrown away. switched to develop the app
this.props.navigation.navigate(userToken ? 'App' : 'LoginScreen');
};
I had the LoginScreen component rendered on my device.
I know the problem come from my AuthNavigator and AppNavigator because I can return screens components from AuthLoading or MainNavigator
Here some code :
* Main Navigator: entry point of the app
* Redirect to AuthLoadingScreen by default,
* if user is signed (AsyncStorage) or successly signIn
* redirect to AppNavigator else if user isn't SignIn
* go to AuthNavigator
import { createAppContainer, createSwitchNavigator } from 'react-
navigation';
import AuthNavigator from './auth/AuthNavigator'
import AppNavigator from './app/AppNavigator'
import AuthLoadingScreen from '../screens/auth/AuthLoadingScreen'
export default createAppContainer(createSwitchNavigator(
{
// You could add another route here for authentication.
// Read more at https://reactnavigation.org/docs/en/auth-flow.html
AuthLoading: AuthLoadingScreen,
App: AppNavigator,
Auth: AuthNavigator,
},
{
initialRouteName: 'AuthLoading',
}
));
AuthLoading :
import React from 'react';
import {
ActivityIndicator,
AsyncStorage,
StatusBar,
StyleSheet,
View,
Text
} from 'react-native';
export default class AuthLoadingScreen extends React.Component {
constructor(props) {
super(props);
this._bootstrapAsync();
}
// Fetch the token from storage then navigate to our appropriate place
_bootstrapAsync = async () => {
const userToken = await AsyncStorage.getItem('userToken');
// This will switch to the App screen or Auth screen and this loading
// screen will be unmounted and thrown away. switched to develop the app
this.props.navigation.navigate(userToken ? 'App' : 'Auth');
};
// Render any loading content that you like here
render() {
return (
<View>
<Text>Loading</Text>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
AuthNavigator:
import { createStackNavigator } from 'react-navigation';
import LoginScreen from '../../screens/auth/LoginScreen';
import SignUpScreen from '../../screens/auth/SignUpScreen';
export default createStackNavigator({
Login : {
screen : LoginScreen
},
SignUp: {
screen : SignUpScreen
}
},
{
initialRouteName: 'Login',
})
LoginScreen:
import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
export default class LoginScreen extends Component {
render() {
console.log('LOGIN SCREEN')
return (
<View style={styles.container}>
<Text style={styles.text}>Login</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
text : {
fontSize: 20,
}
});
I can't find the error, but I know it comes from the AuthNavigator and AppNavigator. I can see the 'LOGIN SCREEN' or 'APP SCREEN' if I set the AuthLoading route to render App in my console but nothing on the screen, when I init a new route LoginScreen in my MainNavigator and navigate to that route from the AuthLoading it works, I have a beautiful text displayed on my screen.
I Know it's probably an insignifiant error but I spend hours to fix this by myself and can't find, so if someone can help me it would be nice!
Thanks by advance!
Problem solved... Because at the top of my app in App.js I wrapped my MainNavigator like that
<View>
<StatusBar hidden={true} />
<MainNavigator />
</View>
So I remove the view and statusbar... and it works. 4 days to figure it out... I love it! :')

The navigation prop is missing for this navigator

Every single example I have seen in Stack Overflow uses the case where the App component is a functional component, but I am using a class-based App component and I am playing catch up with the breaking changes of React Navigation.
This is my code inside App.js file:
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import {
createBottomTabNavigator,
createStackNavigator
} from "react-navigation";
import AuthScreen from "./screens/AuthScreen";
import WelcomeScreen from "./screens/WelcomeScreen";
import MapScreen from "./screens/MapScreen";
import DeckScreen from "./screens/DeckScreen";
import SettingsScreen from "./screens/SettingsScreen";
import ReviewScreen from "./screens/ReviewScreen";
export default class App extends React.Component {
render() {
const MainNavigator = createBottomTabNavigator({
welcome: WelcomeScreen,
auth: AuthScreen,
main: {
screen: createBottomTabNavigator({
map: MapScreen,
deck: DeckScreen,
review: {
screen: createStackNavigator({
review: ReviewScreen,
settings: SettingsScreen
})
}
})
}
});
return (
<View style={styles.container}>
<MainNavigator />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
justifyContent: "center"
}
});
I was refactoring it along nicely and then it broke with this message that I cannot figure out:
Invariant Violation: The navigation prop is missing for this
navigator. In react-navigation 3 you must set up your app container
directly.
Yes, I looked at React Native docs regarding AppContainer and I saw this line of code
const AppContainer = createAppContainer(AppNavigator);
but I am not sure how to refactor mines or not refactor it too much to get this right.
When I try to add this line of code export default createAppContainer(App); at the bottom of my file and obviously removing export default from in front of class App... and also pulling out createAppContainer from inside my react-navigation, I get an error that says:
TypeError: undefined is not an object
Set you createAppContainer like this
import AuthScreen from "./screens/AuthScreen";
import WelcomeScreen from "./screens/WelcomeScreen";
import MapScreen from "./screens/MapScreen";
import DeckScreen from "./screens/DeckScreen";
import SettingsScreen from "./screens/SettingsScreen";
import ReviewScreen from "./screens/ReviewScreen";
import { createBottomTabNavigator, createStackNavigator, createAppContainer } from 'react-navigation';
const MainNavigator = createAppContainer(createBottomTabNavigator({ // set createAppContainer here
welcome: WelcomeScreen,
auth: AuthScreen,
main: {
screen: createBottomTabNavigator({
map: MapScreen,
deck: DeckScreen,
review: {
screen: createStackNavigator({
review: ReviewScreen,
settings: SettingsScreen
})
}
})
}
}));
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<MainNavigator />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
justifyContent: "center"
}
});

Resources