Passing data between screens, route.params, React Native navigation - javascript

I'm trying to pass some data between two screens in my app. I'm using for this route.params from react-navigation
(here is the docs https://reactnavigation.org/docs/params/).
In the first component - home.js - I have an array with some data and FlatList component. Home.js displays data in my app correctly.
In the second component - reviewsDetails.js- I'm trying to display data /item.title/ from
home.js but I have this error: "TypeError: Cannot read properties of undefined (reading 'item')".
I am looking for a solution to this problem
Here is my code:
home.js
import React, { useState } from 'react';
import {StyleSheet, View, Text, FlatList,TouchableOpacity} from 'react-native'
function Home({navigation}) {
const [reviews, setReviews] = useState(
[
{title:"Zelda", rating:1, body:'lorem ipsum', key:1},
{title:"Cruella", rating:1, body:'lorem ipsum', key:2},
{title:"Voldemort", rating:1, body:'lorem ipsum', key:3},
]
)
return (
<View style={styles.container}>
<FlatList
data={reviews}
renderItem={({item})=>(
<TouchableOpacity onPress={()=> navigation.navigate("reviewDetails", item)}>
<Text>{item.title}</Text>
</TouchableOpacity>
)}
/>
</View>
);
}
export default Home;
reviewDetails.js
import React from "react";
import { View, Text, Button, StyleSheet } from "react-native";
export default function ReviewDetails({ route, navigation }) {
const { item } = route.params;
return (
<View style={globalStyles.container}>
<Text>{item.title}</Text>
</View>
);
}
And here is the error
image
Codesandbox with source code: link
I will be grateful for any advice
EDIT.
Additional info :)
Here is also my navigation.js:
mport { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import React from 'react';
import about from '../screens/about'
import home from '../screens/home'
import reviewDetails from '../screens/reviewDetails'
const Tab= createBottomTabNavigator();
const AppNavigator=()=>(
<Tab.Navigator>
<Tab.Screen name="about" component={about}></Tab.Screen>
<Tab.Screen name="home" component={home}></Tab.Screen>
<Tab.Screen name="reviewDetails" component={reviewDetails}></Tab.Screen>
</Tab.Navigator>
)
export default AppNavigator;
and app.js
import React from 'react';
import { NavigationContainer, useNavigation } from "#react-navigation/native";
import AppNavigator from "./navigation/navigation.js"
export default function App(){
return(
<NavigationContainer>
<AppNavigator>
</AppNavigator> </NavigationContainer>
)
}
If its helpfull - I use version 6.0.2 of react-navigation/native and 6.0.7 of react-navigation/stack

You have to pass params like this from home screen. Pass it in an object named data (This can be named as anything you want)
onPress={() => {
navigation.navigate("reviewDetails", {
data: item,
});
}}
And then get it on the next screen like this on reviewDetails screen
const { data } = route.params;

Related

Using a function with "navigate" as a compponent

I am trying to use navigation in react native, but it gives me an error when I try use a component with navigate (LogIn) with the
<Login/>
tags.
It says that navigate is undified so I passed the navigation as a prop with no success
App.js
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { SafeAreaView, StyleSheet, Text, View } from 'react-native';
import Login from "./assets/code/Login.js";
import { NavigationContainer, StackActions } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import 'react-native-gesture-handler';
const Stack = createStackNavigator();
export default function App({ navigation }) {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Welcome to dog app, and I hate react"
component={HomePage}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
function HomePage({ navigation }) {
return (
<View style={styles.container}>
<View>
<Text> {""}Welcome to dogappcoolapp app</Text>
</View>
<View style={styles.blue}>
<Login navigate={ navigation } style={styles.blue} />
</View>
</View>
)
}
The error is in this line
<Login navigate={ navigation } style={styles.blue} />
The error is
The LogIn function is in
LogIn.js
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, Script, Alert } from 'react-native';
import { NavigationContainer, StackActions, } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import 'react-native-gesture-handler';
const Stack = createStackNavigator();
export function Login({navigation}) {
if (true)
return (
navigation.navigate('WelcomePage')
);
}
function WelcomePage () {
return (
<View>
<Button title="enter" />
<Text> dog app dog woof-app{"\n\n\n\n\n\n\n\n\n"}OMG!! YOU ARE LOGGED IN! WELCOME!{"\n\n\n\n\n"}</Text>
</View>
);
}
const styles = StyleSheet.create({
blue: {
flex: 2,
backgroundColor: "dodgerblue",
alignItems: 'center',
justifyContent: 'center',
},
});
export default Login;
If I remove all of the navigation prop and tags from the function LogIn, then I can use LogIn as a componnent with <LogIn/>, but not with navigation, I tried usinng it with
navigate={ navigation }
(As it is in the code that I posted)
and I tried without it, I keep getting similar errors.
How can I use LogIn as a component with </> tags while still having navigation component in it?
The logic is correct, in child components, you can pass a navigation prop to get access to navigation, but you are passing your navigation object to a prop called navigate <Login navigate={ navigation } style={styles.blue} />, no wonder it's undefined, you should receive it as navigate in your Login component.
export function Login({navigation}) { //<-- here you have navigation where the prop name that you pass is navigate.
so it should be
export function Login({navigate}) {
...
navigate.navigate('...')
or you should rename your prop to navigation and then your navigation.navigate won't be undefined anymore.

React Native "TypeError: Object(...) is not a function" Error for react navigation stack

I'm having an issue with my react-navigation-stack, I believe it could be a problem with dependencies, but I'm not sure if that's it. I am simply trying to have some text redirect to another page. If there is code that is irrelevant to the issue, such as a button, I apologize as I am trying to learn react native. The problem is being pointed at homeStack.js at the first import, "import { createStackNavigator } from '#react-navigation/stack';" , but previously I just used react-navigation-stack there, which I believe was a part of old dependencies, but it gave me a module not found error at first, which changed to what I have now when I put #react-navigation/stack instead. I was learning from a video tutorial, but the code from the tutorial was not compiling. I redownloaded react navigation multiple times and have tried some thing that did not work. I will post my code below and would really appreciate help and input as to what can help my problem. Thanks you!
Picture of error
homeStack.js
import { createStackNavigator } from '#react-navigation/stack';
//import { createAppContainer } from '#react-navigation/native';
//import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from 'react-navigation';
import Home from '../screens/home';
import ReviewDetails from '../screens/reviewDetails';
const screens = {
Home: {
screen: Home,
},
ReviewDetails: {
screen: ReviewDetails,
},
};
// home stack navigator screens
const HomeStack = createStackNavigator(screens);
export default createAppContainer(HomeStack);
home.js
import React from 'react';
import { StyleSheet, View, Text, } from 'react-native';
import { globalStyles } from '../styles/global';
export default function Home() {
return (
<View style={globalStyles.container}>
<Text style={globalStyles.titleText}>Home Screen</Text>
</View>
);
}
App.js
//import React from 'react';
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
import Buttonwithbackground from './src/Buttonwithbackground';
import { StackNavigator } from 'react-navigation';
//import Expo from 'expo';
//import Screen from 'screen2';
import { AppLoading } from 'expo';
import Navigator from './routes/homeStack';
import { render } from 'react-dom';
//
//import {Link} from 'react-router-dom';
class HomeScreen extends React.Component{
static NavigationOptions = {
title: 'Home',
};
render(){
const { navigate} = this.props.navigation;
return(
<View style={styles.container}>
<Text
onPress= { ()=> navigate('Home') }>Navigate to Profile
</Text>
</View>
);
}
}
class ProfileScreen extends React.Component{
static NavigationOptions = {
title: 'Profile',
};
render(){
const { navigate} = this.props.navigation;
return(
<View style={styles.container}>
<Text
onPress= { ()=> navigate('Profile') }>Navigate to Profile
</Text>
</View>
);
}
}
//export default function App() {
export default class App extends Component {
editUser = () => {
this.props.navigation.navigate("Screen");
// this.navigation.navigate("screen2");
// window.location.href = 'screen2';
};
editUser2 = () => {
//if the second button is clicked, it will redirect to yahoo.com
window.location.href="http://yahoo.com"
};
render(){
return (
<View style={styles.container}>
<Image
style={{width: 350, height: 200}}
source = {require('./assets/dolanduckjoker.jpg')}
/>
<Navigator />
<Buttonwithbackground text='Login' color='black' onPress={this.editUser2}/>
<p><br/></p>
<Button title='Login' color='black' onPress={this.editUser2}/>
<Button title='Login' color='black' onPress={() => navigation.navigate('screen2.js')}/>
<p><br/></p>
<Button
style={styles.cancelButton}
onPress={this.editUser}
title="Register"
color="#343434"
accessibilityLabel="Register a User."/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 32,
textAlign: 'center',
margin: 10,
},
});
The error says what's wrong -
Object(...) is not a function
createStackNavigator expects a function and you are passing an object to it as a parameter. According to docs
Your code should look like -
import { createStackNavigator } from '#react-navigation/stack';
//import { createAppContainer } from '#react-navigation/native';
//import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from 'react-navigation';
import Home from '../screens/home';
import ReviewDetails from '../screens/reviewDetails';
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="ReviewDetails" component={ReviewDetails} />
</Stack.Navigator>
);
}
export default MyStack; //you need to render this
Now in your root file, It should be something like this (excluding your additional code) -
import { createStackNavigator } from '#react-navigation/stack';
import MyStack from "yourPath";
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}

Nested switchNavigator inside a component with React Navigation

Im stuck with a Nested Navigation System. I have a main navigator (switchNavigator) and one of its screens is a component witch inside has some views and inside of one of this views I want to put another navigator (switchNavigator), but I get this error "The navigation prop is missing for this navigator. In react-navigation v3 and v4 you must set up your app container directly.". I really don't know if it's posible or a valid implementation.
This is my mainNavigator and two simple components, the second one is where I call the nested navigator:
import React from 'react';
import {createAppContainer,createSwitchNavigator} from 'react-navigation';
import { View, Text } from 'react-native';
import NestedNav from './nestedNav';
const FirstView = props=>{
return(
<View>
<Text>First view</Text>
</View>
)
}
const secondView = props=>{
return(
<View>
<View>
<Text>Second view</Text>
</View>
<View>
<NestedNav></NestedNav>
</View>
<View>
<Text>some other ui content</Text>
</View>
</View>
)
}
const MainNavigator = createSwitchNavigator(
{
firstView:FirstView,
secondView:secondView
},
{
initialRouteName: 'secondView',
}
);
export default createAppContainer(MainNavigator)
And this is my NestedNavigator:
import React from 'react';
import {createAppContainer,createSwitchNavigator} from 'react-navigation';
const NestedNav = createSwitchNavigator(
{
firstView:SomeFirstViewInNestedNav,
secondView:SomesecondViewInNestedNav
},
{
initialRouteName: 'firstView',
}
);
export default NestedNav
as you rendered the nestedNavigator it should be in wrapped into a appContainer.
const NestedNav = createSwitchNavigator(
{
firstView:SomeFirstViewInNestedNav,
secondView:SomesecondViewInNestedNav
},
{
initialRouteName: 'firstView',
}
);
--> export default createAppContainer(NestedNav)
I got the solution, I just had to create a static reference of the nested Navigation's Router in my nested navigator container component (in the example "secondView" component):
static router = NestedNav.router
And set the navigation prop to the nested navigator:
<NestedNav navigation = {this.props.navigation}></NestedNav>
This solution is in the Docs: here

Separate Navigation in React Native Navigation

I'm currently figuring out how to reuse a navigation which is declared in it's own class for multiple screens or to put it in another way: If my approach isn't clever react wise, is there another, better way to create a navigation that is reused on multiple screens?
Whenever I'm trying to click a button in the navigation I get an error "undefined is not an object (evaluating _this2.props.navigation.navigate). So I guess that I'm missing something about this.props in the Navigation.js.
I'm using react-navigation because it has been recommended on SO and in the react-native documentation as the way to go.
App.js
import React from 'react';
import {createStackNavigator} from 'react-navigation';
import HomeScreen from './screens/home/HomeScreen'
import ProfileScreen from './screens/profile/ProfileScreen'
import SettingsScreen from './screens/settings/SettingsScreen'
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Profile: ProfileScreen,
Settings: SettingsScreen,
},
{
initialRouteName: 'Home',
}
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
Navigation.js - contains the planned navigation for all screens
import React from 'react';
import {StyleSheet, View, TouchableOpacity, Text} from 'react-native';
class Navigation extends React.Component {
render() {
return (
<View style={navigationStyles.footerWrapper}>
<View style={navigationStyles.footer}>
<TouchableOpacity style={navigationStyles.footerItem}
onPress={() => this.props.navigation.navigate('Home')}>
<Text style={navigationStyles.placeholderIcon}/>
</TouchableOpacity>
<TouchableOpacity style={navigationStyles.footerItem}
onPress={() => this.props.navigation.navigate('Profile')}>
<Text style={navigationStyles.placeholderIcon}/>
</TouchableOpacity>
<TouchableOpacity style={navigationStyles.footerItem}
onPress={() => this.props.navigation.navigate('Settings')}>
<Text style={navigationStyles.placeholderIcon}/>
</TouchableOpacity>
</View>
</View>
);
}
}
const navigationStyles = StyleSheet.create({
//
});
module.exports = Navigation;
HomeScreen.js - screen that should contain the navigation but displays an error when the onPress event is fired
import React from 'react';
import {StyleSheet, View, TouchableOpacity, Text} from 'react-native';
import styles from '../../common/customStyleSheet'
import Navigation from '../../components/navigation/Navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
header: null,
};
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<Text style={homeScreenStyles.paddingMedium}>HomeScreen.</Text>
<Navigation/>
</View>
);
}
}
const homeScreenStyles = StyleSheet.create({
paddingMedium: {
paddingTop: 200,
},
});
module.exports = HomeScreen;
your Navigation component won't automatically inherit the navigation prop from HomeScreen because it is just a subcomponent (it is not defined in the stack navigator like the HomeScreen is). So you need to pass the navigation as a prop to the Navigation component in your HomeScreen JSX.
// HomeScreen.js
render() {
return (
<View style={styles.container}>
<Text style={homeScreenStyles.paddingMedium}>HomeScreen.</Text>
<Navigation navigation={this.props.navigation}/>
</View>
);
}

reactnavigation hiding statusbar leaves space above header

I use reactnavigation and I am hiding the statusbar at the top, but it leaves an empty space above the header.
I already tried paddingTop or marginTop, but none work.
This is how I hide the statusbar.
import React from 'react';
import { Platform, View, StatusBar } from 'react-native';
import { Tabs, Drawer } from './config/router';
const App = () => (
<View style={{flex:1}}>
<StatusBar hidden={true} />
<Drawer />
</View>
);
export default App;
Any idea would be helpful.
Thanks.
How to Fix it
I add the following to the index.js:
import React from 'react';
import { Platform, View, StatusBar } from 'react-native';
import { Tabs, Drawer } from './config/router';
import { SafeAreaView } from 'react-navigation';
SafeAreaView.setStatusBarHeight(0);
const App = () => (
<View style={{flex:1}}>
<StatusBar hidden={true} />
<Drawer />
</View>
);
export default App;
Basically added the SafeAreaView part.
Hope this is helpful for others.
Try the static function Status Bar. You might need to convert the component to a React Component/Pure Component. Try it with and without converting it.
componentDidMount(){
StatusBar.setHidden(true,true);
}

Categories