Stacknavigator not navigating to new screen while using functional component - javascript

Here's my App.js
import React, {Component} from 'react';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import Reducers from './app/reducers';
import Preload from './app/Screens/Preload';
import HomeScreen from './app/Screens/HomeScreen';
let store = createStore(
Reducers,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
const AppNavigator = createStackNavigator({
Home: {screen: HomeScreen, navigationOptions: {header: null }},
Preload: {screen: Preload, navigationOptions: {header: null }},
});
const AppContainer = createAppContainer(AppNavigator);
export default class App extends Component {
render () {
return (
<Provider store={store}>
<AppContainer/>
</Provider>
)
}
}
HomeScreen.js has a nested Wrap.js component which in turn has a Header.js component where the onPress event is handled to load a new screen, in this case the Preload.js screen.
When I press the TouchableOpacity component, there is no error thrown but nothing happens either. The new screen doesn't load. Please let me know how to load new screens while using functional components.
Here are the respective components mentioned above.
Wrap.js
import React from 'react'
import { View, Text, StyleSheet, StatusBar, Platform, SafeAreaView, ScrollView } from 'react-native'
import Colors from '../../Constants/Colors'
import Header from './Header'
const Wrap = (props) => {
return (
<SafeAreaView style={styles.mainWrapper}>
<ScrollView>
<Header />
{props.children}
</ScrollView>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
mainWrapper: {
backgroundColor: Colors.orange,
height: "100%",
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0
}
})
export default Wrap
Header.js
import React from 'react'
import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native'
import { FontAwesome } from '#expo/vector-icons';
import SourceImages from '../../Constants/SourceImages'
import Colors from '../../Constants/Colors'
import { NavigationActions } from 'react-navigation';
const {navigate} = NavigationActions;
const Header = () => {
return (
<View style={styles.wrapper}>
<View style={styles.menuIconWrapper}>
<TouchableOpacity style={styles.iconWrapper}
onPress={()=>{navigate('Preload')}}
>
<FontAwesome name="navicon" style={styles.icon} />
</TouchableOpacity>
</View>
<View style={styles.logoWrapper}>
<Image style={styles.logo} source={ SourceImages.logo } resizeMode="contain" />
</View>
<View style={styles.cartIconWrapper}>
<TouchableOpacity style={styles.iconWrapper} >
<FontAwesome name="shopping-basket" style={styles.icon} />
</TouchableOpacity>
</View>
</View>
)
}
export default Header

You have to do it in following way:
1- import { withNavigation } from 'react-navigation' instead of NavigationActions
2- use const Header = (props) instead of const Header = ()
3- use props.navigation instead of const {navigate} = NavigationActions;
4- export default withNavigation(Header) instead of export default Header
It will work this way:
import { withNavigation } from 'react-navigation'
const Header = (props)
props.navigation.navigate('Preload')
export default withNavigation(Header)

Related

TypeError: undefined is not an object (evaluating 'Object.keys(routeConfigs)') React native Project app

So i'm currently developing a react native application, but i'm getting this error. I think it may have to do with the version of some libraries that i'm using but i'm not sure.
This is my app.js file
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux';
import HomeScreen from './screens/HomeScreen';
import MapScreen from './screens/MapScreen';
import { store } from './store';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import 'react-native-gesture-handler';
import {NavigationContainer} from '#react-navigation/native';
import { createStackNavigator } from "react-navigation-stack";
export default function App() {
const Stack = createStackNavigator();
return (
<Provider store={store}>
<NavigationContainer>
<SafeAreaProvider>
<Stack.Navigator>
<Stack.Screen
name='HomeScreen'
component={HomeScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name='MapScreen'
component={MapScreen}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</SafeAreaProvider>
</NavigationContainer>
</Provider>
);
}
My HomeScreen.js file, which is rendered when the app starts.
import React from 'react'
import { StyleSheet, Text, View, SafeAreaView, Image } from 'react-native'
import tw from 'tailwind-react-native-classnames';
import NavOptions from '../components/NavOptions';
const HomeScreen = () => {
return (
<SafeAreaView style = {tw`bg-white h-full`}>
<View style = {tw`p-5`}>
<Image
style = {{
width: 100,
height: 100,
resizeMode: "contain",
}}
source={{
uri: "https://links.papareact.com/gzs"
}}
/>
<NavOptions/>
</View>
</SafeAreaView>
)
}
export default HomeScreen
My MapScreen.js file, the other screen I have.
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
const MapScreen = () => {
return (
<View>
<Text>Here is the map stuff...</Text>
</View>
)
}
export default MapScreen
The NavOptions.js file, which renders two buttons on the screen to select one.
import { useNavigation } from '#react-navigation/native';
import React from 'react'
import { FlatList, Text, Touchable, TouchableOpacity, View, Image } from 'react-native'
import { Icon } from 'react-native-elements/dist/icons/Icon';
import tw from 'tailwind-react-native-classnames';
const data = [
{
id: "123",
title: "Get a ride",
image: "https://links.papareact.com/3pn",
screen: "MapScreen",
},
{
id:"456",
title:"Order food",
image: "https://links.papareact.com/28w",
screen: "EatsScreen", // Change in future....
}
]
const NavOptions = () => {
const navigation = useNavigation();
return (
<FlatList
data = {data}
horizontal
keyExtractor = {(item) => item.id}
renderItem={({item}) => (
<TouchableOpacity
onPress={() => navigation.navigate(item.screen)}
style = {tw`p-2 pl-6 pb-8 pt-4 bg-gray-200 m-2 w-40`}
>
<View>
<Image
style = {{
width: 120,
height: 120,
resizeMode: "contain",
}}
source={{
uri: item.image
}}
/>
<Text style={tw`mt-2 text-lg font-semibold`}>{item.title}</Text>
<Icon
style = {tw`p-2 bg-black rounded-full w-10 mt-4`}
name="arrowright" color="white" type="antdesign"/>
</View>
</TouchableOpacity>
)}
/>
)
}
export default NavOptions
normally undefined is not a object occurs when you are asking for parameter value from parameter that does not exist.
for example:
let data = [
{
arr:[{name:"aaa"},{name:"bbb"}],
b:'outside1'
},
{
arr:[{name:"ccc"},{name:"ddd"}],
b:'outside2'
},
]
in here if you right data[0].b then it will return outside1
but data[0].b.c will be undefine and data[0].b.c.d will give error undefined is not a object.
in your code I am not seeing any this kind of pattern so please check your code if this is happening anywhere .
For others with the same error but in different context:
I had this issue when I imported modules from 'aws-amplify-react-native', but 'aws-amplfify-react-native' wasn't installed and so it was "undefined"

React Native Error undefined is not an object (evaluating 'navigation.push')

I want to navigate to List.js after I click the button in MainMenu.js file, but it always shows me this error:
TypeError: undefined is not an object (evaluating 'navigation.push')
This is my App.js file
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { List } from './List';
import { MainMenu } from './MainMenu';
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to stassrt working on your app!</Text>
<StatusBar style="auto" />
<MainMenu></MainMenu>
</View>
);
}
And this is my MainMenu.js file (I have the button in this file):
import React from 'react';
import { Text, Button, View, StyleSheet } from 'react-native';
import { ScreenContainer } from 'react-native-screens';
import { List } from './List';
import { useNavigation } from '#react-navigation/core';
export const MainMenu = ({navigation}) => (
<View>
<Text>Hello HOW ARE YsOU</Text>
<Button title="Click" onPress={() => navigation.push("List")}></Button>
</View>
);
In your MainMenu component, you are expecting an object with a key navigation as props. You are not passing any props to the MainMenu, however, and so the props are undefined, but you are expecting an object. To fix this, change the component to:
import React from 'react';
import { Text, Button, View, StyleSheet } from 'react-native';
import { ScreenContainer } from 'react-native-screens';
import { List } from './List';
import { useNavigation } from '#react-navigation/core';
export const MainMenu = () => {
const navigation = useNavigation()
return (
<View>
<Text>Hello HOW ARE YsOU</Text>
<Button title="Click" onPress={() => navigation.push("List")}>
</Button>
</View>
);
};
We are using the hook, instead of props.
I don't know how you implemented the stack navigator, but I think your App.js file should look like this:
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { List } from './List';
import { MainMenu } from './MainMenu';
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<>
<Stack.Screen name="Main Menu" component={MainMenu} />
<Stack.Screen name="List" component={List} />
</>
</Stack.Navigator>
</NavigationContainer>
);
}
And I think your MainMenu component should look like this:
import React from 'react';
import { Text, Button, View, StyleSheet } from 'react-native';
import { ScreenContainer } from 'react-native-screens';
import { List } from './List';
export const MainMenu = ({navigation}) => (
<View style={styles.container}>
<Text>Open up App.js to stassrt working on your app!</Text>
<StatusBar style="auto" />
<View>
<Text>Hello HOW ARE YsOU</Text>
<Button title="Click" onPress={() => navigation.navigate("List")</Button>
</View>
</View>

Trying to access route.params in react native stack navigator v5

I am trying to access the props.route.params.data information from the react navigation route prop, however when I try to output it on the screen it just says TypeError: undefined is not an object(evaluating props.routes.params). I know I have correctly followed the path to that data object because I console.log it on the console and it outputs that data. However when I want to put put it on the user interface it gives me that error. Been searchong online but no one has the same issue, maybe because the way to get the params using react stack navigator v5 is by route.params, and v5 came outa couple of months ago. So I will post my code below along with the console.log screen, the error message, and also the object that I am picking from. Thank you!
// App.js
import 'react-native-gesture-handler';
import React from 'react';
import { View , StyleSheet } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import About from "./screens/About";
import Home from "./screens/Home";
import PokeDetails from "./screens/PokeDetails"
import { createStackNavigator } from '#react-navigation/stack';
const App =()=> {
const Stack = createStackNavigator();
return(
<View style={styles.container}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home}/>
<Stack.Screen name="PokeDetails" component={PokeDetails}/>
<Stack.Screen name="About" component={About}/>
</Stack.Navigator>
</NavigationContainer>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1
}
})
export default App;
// Home.js
import React, { useState } from "react";
import { View, Text , Button, FlatList, ActivityIndicator, TouchableOpacity, Image } from "react-native";
import { GlobalStyles } from "../styles/GlobalStyles";
import PokeDetails from "./PokeDetails";
import { useRoute } from '#react-navigation/native';
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
}
}
componentDidMount() {
fetch(`https://pokeapi.co/api/v2/pokemon/?limit=20`)
.then((res)=> res.json())
.then((response)=> {
this.setState({
isLoading: false,
dataSource: response.results,
})
console.log("RESPONSE",response)
console.log("RESPONSE.RESSSULTS",response.results)
})
}
render() {
const showIndicator = this.state.isLoading == true ? <ActivityIndicator size="large" color="#0000ff" /> : null;
return(
<View style={GlobalStyles.container}>
<View style={GlobalStyles.activityIndicator}>{showIndicator}</View>
<FlatList
keyExtractor={(item, index) => item.name}
numColumns={1}
data={this.state.dataSource}
renderItem={({item})=>
<TouchableOpacity onPress={()=> this.props.navigation.navigate('PokeDetails',
{data:"hello"})}>
<PokeDetails imageUrl={`https://projectpokemon.org/images/normal-sprite/${item.name}.gif`} name={item.name}/>
</TouchableOpacity>
}/>
<Button onPress={()=> this.props.navigation.navigate("About")} title="Go to about"/>
</View>
)
}
}
export default Home;
// PokeDetails.js
import React from "react";
import { View, Text , Image, Button} from "react-native";
import {GlobalStyles} from "../styles/GlobalStyles";
import { TouchableOpacity } from "react-native-gesture-handler";
import { useRoute } from '#react-navigation/native';
const PokeDetails =(props)=> {
console.log(props)
console.log(props.route.params.data, "PROPSSSSSSSSSSS");
return(
<View style={GlobalStyles.container}>
<Image source={{uri: props.imageUrl}} style={{height: 50, width: 50}}/>
<Text>{props.route.params.data}</Text>
</View>
)
}
export default PokeDetails;
You are getting the following error because you are pokedetails in your home screen, you can get the data props only if you navigate to pokedetails screen, the thing you can do something like this:
change your Home.js like this:
import React, { useState } from "react";
import { View, Text , Button, FlatList, ActivityIndicator, TouchableOpacity, Image } from "react-native";
import PokeDetails from "./Pokedetails";
import { useRoute } from '#react-navigation/native';
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
}
}
componentDidMount() {
fetch(`https://pokeapi.co/api/v2/pokemon/?limit=20`)
.then((res)=> res.json())
.then((response)=> {
this.setState({
isLoading: false,
dataSource: response.results,
})
console.log("RESPONSE",response)
console.log("RESPONSE.RESSSULTS",response.results)
})
}
render() {
const showIndicator = this.state.isLoading == true ? <ActivityIndicator size="large" color="#0000ff" /> : null;
return(
<View>
<View>{showIndicator}</View>
<FlatList
keyExtractor={(item, index) => item.name}
numColumns={1}
data={this.state.dataSource}
renderItem={({item})=>
<TouchableOpacity onPress={()=> this.props.navigation.navigate('PokeDetails',
{data:"hello", imageUrl:`https://projectpokemon.org/images/normal-sprite/${item.name}.gif`})}>
<PokeDetails imageUrl={`https://projectpokemon.org/images/normal-sprite/${item.name}.gif`} name={item.name}/>
</TouchableOpacity>
}/>
<Button onPress={()=> this.props.navigation.navigate("About")} title="Go to about"/>
</View>
)
}
}
export default Home;
Here iam just passing imageUrl also for reference purpose.
change your pokedetails.js some thing like this:
import React from "react";
import { View, Text , Image, Button} from "react-native";
import { TouchableOpacity } from "react-native-gesture-handler";
import { useRoute } from '#react-navigation/native';
const PokeDetails =(props)=> {
console.log("props is",props);
if(props.navigation == undefined)
{
return(
<View>
<Image source={{uri: props.imageUrl}} style={{height: 50, width: 50}}/>
<Text>{props.name}</Text>
</View>
)
}
else{
return(
<View>
<Image source={{uri: props.route.params.imageUrl}} style={{height: 50, width: 50}}/>
<Text>{props.route.params.data}</Text>
</View>
)
}
}
export default PokeDetails;
Here iam just adding a if condition to check whether the screen is loaded is navigated from another screen.
when the Homescreen loaded it will be something like this:
On clicking bulbassor you will be navigating to the pokedetails screen where here iam showing the details you are sending through navigation:
Hope this helps!

How to implement details screen that dynamically displays detail of pokemon when a user presses on a picture in react native?

So I have built a pokemon application that would display pokemon with their images and details. On the homescreen, I have it so that the first 20 pokemon are shown as a preview. Then if the user wants to learn more about the pokemon, they can press on the pokemon and it would bring the user to the "PokeDetails" screen. However, when I press on the pokemon, it brings me to the "PokeDetails" page but the page is blank. Except for the text that I explicitly render from the "PokeDetails" screen. I have the code for both screens below. Any help is appreciated. Thank you
//Home.js
import React, { useState } from "react";
import { View, Text , Button, FlatList, ActivityIndicator, TouchableOpacity, Image } from "react-native";
import { GlobalStyles } from "../styles/GlobalStyles";
import PokeDetails from "./PokeDetails";
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
}
}
componentDidMount() {
fetch(`https://pokeapi.co/api/v2/pokemon/?limit=20`)
.then((res)=> res.json())
.then((response)=> {
this.setState({
isLoading: false,
dataSource: response.results,
})
console.log("RESPONSE",response)
console.log("RESPONSE.RESSSULTS",response.results)
})
}
render() {
const showIndicator = this.state.isLoading == true ? <ActivityIndicator size="large" color="#0000ff" /> : null;
return(
<View style={GlobalStyles.container}>
<View style={GlobalStyles.activityIndicator}>{showIndicator}</View>
<FlatList
numColumns={1}
data={this.state.dataSource}
renderItem={({item})=>
<TouchableOpacity onPress={()=> this.props.navigation.navigate("PokeDetails", {item} )}>
<PokeDetails imageUrl={`https://projectpokemon.org/images/normal-sprite/${item.name}.gif`} name={item.name} item={item} />
</TouchableOpacity>
}/>
<Button onPress={()=> this.props.navigation.navigate("About")} title="Go to about"/>
</View>
)
}
}
export default Home;
// PokeDetails.js
import React from "react";
import { View, Text , Image, Button} from "react-native";
import {GlobalStyles} from "../styles/GlobalStyles";
import { TouchableOpacity } from "react-native-gesture-handler";
import { useRoute } from '#react-navigation/native';
const PokeDetails =({name, imageUrl, detail, route})=> {
return(
<View style={GlobalStyles.container}>
<Text>This text is written expilictly</Text>
<Text>{route.params.item}</Text>
</View>
)
}
export default PokeDetails;
// Root.js
import React from "react"
import { createStackNavigator } from "#react-navigation/stack";
import Home from "../screens/Home";
import PokeDetails from "../screens/PokeDetails";
import { NavigationContainer } from '#react-navigation/native';
const Root =() => {
const Stack = createStackNavigator();
return(
<Stack.Navigator>
<Stack.Screen name="Home" component={Home}/>
<Stack.Screen name="PokeDetails" component={PokeDetails}/>
</Stack.Navigator>
)
}
export default Root;
// App.js
import 'react-native-gesture-handler';
import React from 'react';
import { View , StyleSheet } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from "#react-navigation/drawer";
import About from "./screens/About";
import Root from "./Route/Root";
import PokeDetails from "./screens/PokeDetails"
const App =()=> {
const Drawer = createDrawerNavigator();
return(
<View style={styles.container}>
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Root}/>
<Drawer.Screen name="About" component={About}/>
</Drawer.Navigator>
</NavigationContainer>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1
}
})
export default App;
I don't know if i understood your question. You already pass an item props to your PokeDetails component from your Homescreen, but there is no item in the props your receive in it. just add it and i guess you will access to your data and will be able to display it:
const PokeDetails =({name, imageUrl, detail, item})=> {
return(
<View style={GlobalStyles.container}>
<Image source={{uri: imageUrl}} style={{height: 50, width: 50}}/>
<Text style={GlobalStyles.pokeText}>{name}</Text>
<Text>This text is explicitly written</Text>
// add your stuff here...
<Text>{item.something}</Text>
</View>
)
}
By the way, since you already have the item prop, you can remove the name which already comes from item :)

How to add drawer in react native?

Hello I have a simple app and i want to add a drawer to him I use react-navigation 4x and use react-navigation-drawer to implement Drawer in my app
I used it before sperate drawer in a single package and it's worked fine
but when I use the new package I got this error
Invariant Violation: Invariant Violation: Element type is invalid:
expected a string (for built-in components) or a class/function (for
composite components) but got: undefined. You likely forgot to export
your component from the file it's defined in, or you might have mixed
up default and named imports.
although I export my screen
here is Code
**navigator.js**
import React from 'react';
import {TouchableOpacity, View} from 'react-native';
import Icon from 'react-native-vector-icons';
import {createAppContainer, createSwitchNavigator} from 'react-navigation';
import {
createDrawerNavigator,
NavigationDrawerStructure,
} from 'react-navigation-drawer';
import {createStackNavigator} from 'react-navigation-stack';
import ForgetPassword from '../screens/ForgetPassword';
import Home from '../screens/Home';
import Splash from '../screens/Splash';
const AuthStackNavigator = createStackNavigator({
Authloading: {
screen: Splash,
navigationOptions: {
header: null,
},
},
});
const HomeStack = createStackNavigator({
HomeScreen: {
screen: Home,
navigationOptions: ({navigation}) => ({
title: 'Home',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerRight: (
<TouchableOpacity
onPress={() => navigation.navigate('Notifications')}
style={{margin: 10}}>
<Icon name="ios-notifications" size={28} color="#1DA1F2" />
</TouchableOpacity>
),
}),
},
});
const DrawerNavigator = createDrawerNavigator({
HomeDrawer: {
screen: HomeStack,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: () => <Icon name="ios-home" size={28} color="#0496FF" />,
},
},
});
const Navigations = createSwitchNavigator({
// Authloading: Splash,
Auth: AuthStackNavigator, // the Auth stack
App: DrawerNavigator, // the App stack,
});
const Navigator = createAppContainer(Navigations);
export default Navigator;
**Home.js**
//import liraries
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
// create a component
class Home extends Component {
render() {
return (
<View style={styles.container}>
<Text>Home</Text>
</View>
);
}
}
//make this component available to the app
export default Home;
**App.js**
import React, {Component} from 'react';
import Navigator from './src/navigations/navigator';
class App extends Component {
render() {
return <Navigator />;
}
}
export default App;
Edit
i just think NavigationDrawerStructure it's exports from react-native-drawer so that's my bad :)
so here is the component name as NavigationDrawerStructure
//Navigation Drawer Structure for all screen
class NavigationDrawerStructure extends Component {
//Structure for the navigatin Drawer
toggleDrawer = () => {
//Props to open/close the drawer
this.props.navigationProps.toggleDrawer();
};
render() {
return (
<View style={{flexDirection: 'row'}}>
<TouchableOpacity onPress={this.toggleDrawer}>
<Icon
name="ios-menu"
size={40}
style={{margin: 10}}
color="#1DA1F2"
/>
</TouchableOpacity>
</View>
);
}
}
OR just add a button for a toggle in heder left inside Home stack like this
navigationOptions: ({navigation}) => ({
title: 'Home',
headerLeft: (
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<Icon
name="ios-menu"
size={40}
style={{margin: 10}}
color="#1DA1F2"
/>
</TouchableOpacity>
)
})
Import is invalid. it don't have these objects inreact-navigation-drawer
import { createDrawerNavigator } from 'react-navigation-drawer';
import NavigationDrawerStructure from 'your file path'
instead
import {
createDrawerNavigator,
NavigationDrawerStructure,
} from 'react-navigation-drawer';

Categories

Resources