tired but i want to implement react native stack navigation.
import React, { useState } from "react";
const StackScreen = () => {
let InitialRoute;
let First;
let Second;
let Third;//assume they are screens of my app.
const [stack, setStack] = useState([InitialRoute]);
const replace = (screenName: any) => {
const tmp: Array<any> = stack.filter((el: any) => el = !screenName);
setStack([...stack, screenName]);
}
const navigate = (screenName: any) => {
stack.indexOf(screenName) == -1 ? setStack([...stack, screenName]) : replace(screenName);
}//navigate to another screen
const goBack = () => {
if (stack.length > 1) {
const tmp = [...stack];
tmp.pop();
setStack(tmp);
}
}//they are fuctions.
return stack[stack.length - 1];
}
const App = () => {
return (
<View>
<Appbar />
<StackScreen />
<BottomTab or anything i dont want to render while change screens./>
</View>
)
}
i make toy example even if it's not accurate with reality.
but i have question.
i enter the FirstScreen to SecondScreen. after a while, i pop the secondScreen.
in this case, my code will re-render the FirstScreen.
is the screen re-rendered in react - navigation?
if ans is no, how to i implement without rendering?
what is problem of my idea?
To Implement stack navigation in react native first add these packages https://reactnavigation.org/docs/getting-started according to your environment (EXPO CLI/React-native CLI) .
Stack Navigation Example
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>press back button to go back</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Stack navigation Basic concept
Stack Navigation Mean first Screen In last out. it mean, that that screen which display first and navigate to other and other screen, by pressing back button that first screen will display in last.
In react-navigation, your component will not automatically be re-rendered. See Refresh previous screen on goBack() for discussion on solutions to this issue in react-navigation.
This question is pretty general and I'm not sure how to answer. Can you give more detail on the feedback you're looking for?
Related
When I try to add an to the option headerTitle it displays correctly on Android, but not on iOS. Could anyone help me with this issue?
The stack screen is in a Drawer but i don't think that would change the behaviour.
Difference
I was expecting the header to get the height that the image needs but the header doesn't get the height where in Android it does.
Stack screen
<Stack.Navigator initialRouteName="CandidateView">
<Stack.Screen options={{title: "Kandidaten lijst"}} name="CandidateView" component={CandidateView}/>
<Stack.Screen
name="CandidateDetailView"
component={CandidateDetailView}
></Stack.Screen>
</Stack.Navigator>
Screen in the stack
import {Platform, Text, View} from 'react-native';
import {IconButton} from "react-native-paper";
import {Candidate} from "./CandidateView";
export default function CandidateDetailView({navigation, route}){
const { candidateId } = route.params;
let data: Candidate = {
username: "John Doe",
email: "John.doe#ubeeo.nl",
candidateId: 1234
}
React.useEffect(() => {
// Use `setOptions` to update the button that we previously specified
// Now the button includes an `onPress` handler to update the count
navigation.setOptions({
headerTitleAlign: 'center',
headerTitle: () => (
<View style={{alignItems:'center'}}>
<IconButton icon="account-circle" size={50} style={{alignItems: 'center', justifyContent: 'center'}}/>
<Text>{data.username}</Text>
<Text>{data.email}</Text>
</View>
),
});
}, [navigation]);
return (
<>
<View>
<Text>{JSON.stringify(candidateId)}</Text>
</View>
</>
);
}```
import { SafeAreaView, ScrollView, StyleSheet, View, Text } from 'react-native';
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { Container, Content, List, ListItem } from 'native-base';
import Video from 'react-native-video';
function VideoListScreen({ navigation }) {
return (
<Container>
<Content>
<List>
<ListItem onPress={()=> navigation.navigate('Video Player', {
external: true,
videoURL: 'https://www.w3schools.com/html/mov_bbb.mp4'
})}>
<Text>External video source</Text>
</ListItem>
</List>
</Content>
</Container>
);
}
function VideoPlayerScreen({ route, navigation }) {
const {external, videoURL } = route.params;
return (
<Container>
<Video
source={{uri: videoURL}} // Can be a URL or a local file.
style={styles.backgroundVideo}
/>
</Container>
);
}
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name ='Video List' component={VideoListScreen} />
<Stack.Screen name ='Video Player' component={VideoPlayerScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
I want to play video when the user taps on the item in the list, but right now im getting an error -> Component Exception, undefined is not an object (evaluating 'RTCVideoInsance.Constants'),
this is the video player library im using https://github.com/react-native-video/react-native-video.
Thanks for the help
Running pod install in cd ios after yarn install
source : https://github.com/react-native-video/react-native-video/issues/1502
if you already install pod then try to clean xcode project and then build again.
This will help if developing with expo
1). expo install expo-av
2). Your App.js should be look like this.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Video } from 'expo-av';
export default class App extends React.Component {
render(){
return (
< View style={styles.container} >
< Text >Open up App.js to start working on your app!< / Text >
< Video
source={{ uri: 'https://www.yourdomain.com/uploads/video_file.mp4' }}
shouldPlay
useNativeControls
style={{ width: "100%", height: "50%" }}
/>
</ View >
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
3). Then expo start
I'd like to use the React Navigation v5 (Drawer navigation) with Next.js but I have a question about their integration.
In short: React Navigation (Drawer navigation) based on the React Navigation Screens component.
It conditionally renders the correct Screen.
The problem is: Next.js has it's own routing system based on the Folder structure. eg. each file in /pages folder automatically generates an appropriate route so I can't add these files as a React Navigation Screen (at least I'm not sure it's possible at all)
How to make these tools to work together and save the Next.js SSR feature?
Example of the React Navigation Drawer:
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Thanks for any help!
You should use file based routing system from Nextjs on web and do your own navigation on mobile using React Navigation.
Below is my approach,
// this is how your directory might look like
- pages/
- index.tsx // this is your entry point for web
- about.tsx
App.tsx // this is your entry point for native
// pages/index.tsx
import React from 'react';
import { Text, View } from 'react-native';
const Home: React.FC = () => (
<View>
<Text>Welcome to Expo + Next.js 👋</Text>
</View>
);
export default Home;
// pages/about.tsx
import React from 'react';
import { Text, View } from 'react-native';
const About: React.FC = () => (
<View>
<Text>This is about page!</Text>
</View>
);
export default About;
Define your navigator for native app in App.tsx, it will only work on mobile so it doesn't have to be the same as what you have in pages/ folder. (actually if you only want your app run in browser, you don't need it at all.
Nextjs will handle all the route things, SSR etc... just like a normal Nextjs app when you run it in a browser.
// App.tsx
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import Home from '../pages/index';
import About from '../pages/about';
const Drawer = createDrawerNavigator();
const App: React.FC = () => (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="About" component={About} />
</Drawer.Navigator>
</NavigationContainer>
);
export default App;
The important thing is how should you change routes when you have your navigation on native app but an automatically routing system on web?
There is a package to solve this expo-next-react-navigation, check the documentation for details! Make sure you're using the correct version of this package, if you're using React Navigation 5, you should install expo-next-react-navigation#1.1.6 at this moment.
And here is an example, it should work on both platforms,
import React from 'react';
import { FlatList, Text } from 'react-native';
import { Link } from 'expo-next-react-navigation';
const links = [
{ key: 'home', route: '' },
{ key: 'about', route: 'about' },
];
const Links: React.FC = () => (
<FlatList
data={links}
renderItem={({ item }) => (
<Link routeName={item.route}>
{item.key}
</Link>
)}
/>
);
export default Links;
Before I begin, I'd like to say that there were other questions that were answered that had a similar problem but none of those solutions worked for me. I just started using React Native Expo today and I'm finding the navigation part a little difficult. Take a look at the code:
App.js
import React, { Component } from 'react';
import HomePage from './HomePage'
import DetailsPage from './DetailsPage'
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="HomePage" component={HomePage} />
<Stack.Screen name="DetailsPage" component={DetailsPage} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
I've got 2 .js files that represent 2 pages of my app, here's the code for those files:
HomePage.js
import React, { useState } from 'react';
import { StyleSheet, Text, View, SafeAreaView, FlatList, TouchableOpacity } from 'react-native';
export default function HomePage() {
// Create a temporary list to populate the table view
const [orders, setOrders] = useState([
{ company: 'Airbnb', date: '20/02/2020', author: 'Mohammed Ajmal', itemOrdered: 'Sack Craft paper', id: '1' },
{ company: 'Apple', date: '15/01/2020', author: 'Ilma Ajmal', itemOrdered: 'Multiwall paper sacks', id: '2' },
{ company: 'Google', date: '30/12/2019', author: 'Rifka Ajmal', itemOrdered: 'Rigid paper sacks', id: '3' },
{ company: 'Facebook', date: '29/06/2020', author: 'Fahim Khalideen', itemOrdered: 'Paper bags', id: '4' },
])
return (
<View style={styles.container}>
<SafeAreaView>
{/* Create the table view */}
<FlatList
style = {styles.tableView}
data = {orders}
keyExtractor = {(item) => item.id}
renderItem = {({ item }) => (
<TouchableOpacity style = {styles.tableViewItem} onPress = {() => {
navigation.navigate('DetailsPage')
}}>
<Text style = {styles.companyName}>{ item.company }</Text>
<Text style = {styles.date}>{ item.date } | { item.author }</Text>
<Text style = {styles.itemOrdered}>{ item.itemOrdered }</Text>
</TouchableOpacity>
)}
/>
</SafeAreaView>
</View>
);
}
// Stylesheet
DetailsPage.js
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function DetailsPage() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
What I'm trying to create is a table view, when clicked, it should take the user to the Details page, but I'm getting an error saying
Can't find variable: navigation
I tried almost everything I could find in Stack Overflow but nothing helped me, maybe because the code in those answers were different and I couldn't understand how to make it work for mine.
You are not having a parameter for the navigation change the
line
export default function HomePage() {
to
export default function HomePage({navigation}) {
And it will work.
Or you could make use of the withNavigation when using a class component.
import { withNavigation } from 'react-navigation';
class DetailsPage extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" />
</View>
);
}
}
export default withNavigation(DetailsPage);
I want to have drawer labels/separators in the drawer navigator.
Somewhat like this
How would I do this?
Easy. What you are looking at is called contentComponent. Basically you will need to inject a contentComponent prop into your Drawer navigator.
contentComponent Component used to render the content of the drawer, for example, navigation items. Receives the navigation prop for the drawer. Read more here
import DrawerContent from '../app/components/DrawerContent'
const drawerConfiguration = {
initialRouteName: 'MainStackNavigatior',
headerMode: 'screen',
drawerWidth: deviceWidth / 1.38,
contentComponent: DrawerContent
}
Where contentComponent is just a ScrollView containing a list of customisable items.
class DrawerContent extends Component {
onItemPress(item) {
const { navigation } = this.props;
navigation.navigate(item.key);
}
renderDrawerItem(route) {
const { drawerItems } = this.props;
if (drawerItems.indexOf(route.key) > -1) {
return (
<TouchableOpacity style={styles.drawerItem} key={route.key} onPress={() => this.onItemPress(route)}>
<Text>{route.routeName}</Text>
</TouchableOpacity>
);
}
return null;
}
render() {
const { navigation, isFetching, drawerItemsTitle } = this.props;
return (
<View style={styles.container}>
{!isFetching && <View style={styles.drawerItemTitle}>
<Text style={styles.drawerItemTitleText}>{drawerItemsTitle}</Text>
</View>}
{!isFetching && <View>
{navigation.state.routes.map(route => this.renderDrawerItem(route))}
</View>}
{isFetching && <View style={styles.spinnerViewBg}>
<View style={styles.spinner}>
<ActivityIndicator
size="small"
animating
/>
</View>
</View>}
</View>
);
}
}
Here's a good example from Infinite Red. Tutorial link
As for the separators, it is basically a View with minimal height and certain width. I believe you can figure it out :) Good luck!