TypeError: undefined is not an object (evaluating 'Navigation.navigate') - react-navigation

I am having an error which is showing
TypeError: undefined is not an object (evaluating 'Navigation.navigate')
i were tried to fix this error but didnt work, I also search the error on network but i am getting other content steps
There My Codes:
export const App = ({ Navigation }) => {
/*My Codes*/
<TouchableOpacity onPress={() => Navigation.navigate("DetailsPage2")>
/*My Object*/
</TouchableOpacity>
I wanted To Switch Pages By clicking on the object using onPress and use arrow function but it shows the error, I tried These Steps to resolve it but it also didnt work These are The steps below which i used to fix the error
onPress={() => Navigation.getParam("DetailsPage2") and
onPress={() => Navigation.push("DetailsPage2")
I imported all the imports which i need Like
import React, { useState, useRef, useEffect, createRef, useCallback, } from "react"; import { View, Text, Image, ScrollView, TextInput, StyleSheet, Switch, Animated, Dimensions, Vibration, Alert, KeyboardAvoidingView, Platform, TouchableWithoutFeedback, TouchableOpacity, SafeAreaView, } from "react-native"; import { Svg, Path, Defs, RadialGradient, LinearGradient, Stop, Ellipse, Rect, } from "react-native-svg";
Sorry I Cannot Show My Main Code, If I Show It.
It Could Be Stolen

This error is occurring because the 'Navigation' object is not defined in the App component. It is not being imported correctly.
Make sure that the navigation object is being passed in as a prop to the App component and that it is being imported correctly.
Replace Navigation with navigation:
export const App = ({ navigation }) => {
/*My Codes*/
<TouchableOpacity
onPress={() => navigation.navigate("DetailsPage2")>
/*My Object*/
</TouchableOpacity>
}
Here is the official doc related to this issue reference link.
& React Navigation official website for explore more Link.

Related

How to get navigation object outside Screen

I have the following code in the App.tsx:
export default function App() {
...
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="StackNavigation"
drawerContent={(props) => <MainPageDrawer {...props} />}
screenOptions={{ swipeEnabled: false }}
>
<Drawer.Screen name="StackNavigation" component={StackNavigator} />
</Drawer.Navigator>
</NavigationContainer>
);
...
}
As you see, the MainPageDrawer component isn't inside the Drawer.Screen component. But I still need to get access to navigation object inside MainPageDrawer. When I do something lake this inside MainPageDrawer:
const navigation = useNavigation<MainScreenNavigationProp>();
I get the following error:
Couldn't find a navigation object. Is your component inside a screen in a navigator?
What is the right way to get access to the navigation object outside Screen component?
Solution: I figured out that useNavigation won't work anyway if it is outside Screen, BUT this:
(props) => <MainPageDrawer {...props} />
still pass navigation through props, so you can easily access it without useNavigation. I simply restructured navigation:
function MainPageDrawer({ navigation }) {
...
}
And it works

Why in react native Image is not displaying in simulator?

I am new in react native and want to display images, i setup project with expo and try following code for displaying image i do some research but i think code is right, i don't know why it's not displaying in simulator, Do anyone have any idea.
code:
import React from 'react';
import { View, Text, StyleSheet, Image } from 'react-native';
const ImageDetail = (props) => {
return (
<View>
<Image source={require('./beach.jpg')} />
<Text>{props.title}</Text>
</View>
)
};
const style = StyleSheet.create({
});
export default ImageDetail;
I have image in same folder where file is.
Provide a style with height and width for the Image, without that the image component wont display the image.
<Image style={{height:100,width:100}} source={require('./beach.jpg')} />

react-navigation tabBarComponent cannot read property "key" of undefined

The documentation for react-navigation is pretty unclear to me about how to customise the tabBarComponent beyond simply changing colours. I am able to create my custom component for tabs and point to it like so;
import { TabNavigator } from 'myComponentsSomewhere'
...
const Navigator = createBottomTabNavigator(
{
Route1: Route1Component,
Route2: Route2Component,
...
},
{
tabBarComponent: props => <TabNavigator {...props} />,
tabBarOptions: {
activeTintColor: colors.first,
showLabel: false,
},
},
)
On the TabNavigator side, i get a load of props as i would expect;
activeTintColor: "#d85089",
getAccessibilityLabel,
getButtonComponent,
...
navigation,
...
Within the navigation prop, i can get to the state and then the routes etc... but i am unable to fire off any of the functions for getting buttons or rendering icons. (renderIcon, getButtonComponent)
The docs on these functions are weak, but looking at the code, it seems they both require a "route" object that contains a key, routeName etc.
That shape can be found in the navigation.state.routes array - but passing one of those objects simply throws the error;
Cannot read property 'key' of undefined
Here is an example of that code that errors;
import React from 'react'
import { View, Text } from 'react-native'
const TabNavigator = props => {
return props.navigation.state.routes.map(route =>
props.getButtonComponent(route),
)
}
export default TabNavigator
Ultimately, i want to be able to write my own code to contain the tabs, rather than be restricted to passing code to the react-navigation markup. I don't understand why none of the render functions received in the props will work when passed a complete route object, straight out of the navigation prop
It turns out i was not reading the error properly, which actually told me everything i needed to know...
Cannot read property 'key' of undefined
getButtonComponent (and all the other getting functions in navigation prop) required an object with route included, not just the route.
getButtonComponent({ route }) rather than getButtonComponent(route)
Simplicity wins...

undefined this.props.nnavigation.navigate('screen'), how to fix?

Im trying to use Drawer navigation. I have header.js components which has a hamburger icon to open the left navigation menu
//Header.js
import React from 'react';
import { Text, View, Image, TouchableHighlight} from 'react-native';
import { DrawerNavigator } from 'react-navigation';
// Make a component
const Header = (props, {navigate}) => {
const { textStyle, viewStyle, imgstyle } = styles;
return (
<View style={viewStyle}>
<TouchableHighlight onPress={()=> this.props.navigation.navigate('DrawerToggle')}> //here the error is coming
<Image style={{width:40, height:40}}
source={require('./../media/hamburger.png')}
/>
</TouchableHighlight>
<Text style={textStyle}>{props.headerText}</Text>
</View>
);
};
export default Header;
Here is App.js
const MyApp = DrawerNavigator({
Login: {
screen: Login,
},
Signup: {
screen: Signup,
},
});
export default class App extends React.Component {
render() {
return <MyApp />;
}
}
Here is one of the comoponent Login.js
import React, { Component } from 'react';
import {
Text, View, StyleSheet
} from 'react-native';
import Header from './Header';
export default class Login extends Component{
static navigationOptions = {
drawerLabel: 'Login',
};
render(){
return(
<View >
<Header headerText={'Login'}/>
<Text>Login Screen</Text>
</View>
);
}
}
I am not sure what I am missing to fix this. Please check my code.
EDITED:
I tried without "this" to but no luck. I am checking everywhere in the internet but couldn't find the exact solution or I couldn't get a solution to my mind. Can someone who is good with react native respond on this, Please?
The problem is - you use this keyword in a stateless component: this.props.navigation.navigate('DrawerToggle').
Try just props.navigation.navigate('DrawerToggle') since this is not pointing to the Header component instance in your case.
this in a stateless component is "inherited" from the calling scope (since stateless component is an "arrow" function) and likely points to window or global.

Animated page transitions in react

The past couple of weeks I've been working on an app using React. So far everything is working fine, but now I want to add some transitions to it. These transitions are a bit more complex than any examples I managed to find.
I've got 2 pages, an overview and a detail page which I'd like to transition between.
I'm using react-router to manage my routes:
<Route path='/' component={CoreLayout}>
<Route path=':pageSlug' component={Overview} />
<Route path=':pageSlug/:detailSlug' component={DetailView} />
</Route>
Overview looks like this:
Detailview looks like this:
The idea of the transition is that you click on one of the elements of the Overview. This element which has been clicked moves towards the position it should have on the detailView. The transition should be initiated by a route change (I think) and should also be able to happen in reverse.
I've already tried using ReactTransitionGroup on the Layout, which has a render method which looks like this:
render () {
return (
<div className='layout'>
<ReactTransitionGroup>
React.cloneElement(this.props.children, { key: this.props.location.pathname })
</ReactTransitionGroup>
</div>
)
}
This will give the child component the ability to receive the special lifecycle hooks. But I'd like to access the child components somehow during these hooks and still keep doing things the React way.
Could someone point me in the right direction for the next step to take? Or maybe point me to an example which I may have missed somewhere? In previous projects I used Ember together with liquid fire to get these kinds of transitions, is there maybe something like this for React?
I'm using react/react-redux/react-router/react-router-redux.
Edit: Added a working example
https://lab.award.is/react-shared-element-transition-example/
(Some issues in Safari for macOS for me)
The idea is to have the elements to be animated wrapped in a container that stores its positions when mounted. I created a simple React Component called SharedElement that does exactly this.
So step by step for your example (Overview view and Detailview):
The Overview view gets mounted. Each item (the squares) inside the Overview is wrapped in the SharedElement with a unique ID (for example item-0, item-1 etc). The SharedElement component stores the position for each item in a static Store variable (by the ID you gave them).
You navigate to the Detailview. The Detailview is wrapped into another SharedElement that has the same ID as the item you clicked on, so for example item-4.
Now this time, the SharedElement sees that an item with the same ID is already registered in its store. It will clone the new element, apply the old elements position to it (the one from the Detailview) and animates to the new position (I did it using GSAP). When the animation has completed, it overwrites the new position for the item in the store.
Using this technique, it's actually independent from React Router (no special lifecycle methods but componentDidMount) and it will even work when landing on the Overview page first and navigating to the Overview page.
I will share my implementation with you, but be aware that it has some known bugs. E.g. you have to deal with z-indeces and overflows yourself; and it doesn't handle unregistering element positions from the store yet. I'm pretty sure if someone can spend some time on this, you can make a great little plugin out of it.
The implementation:
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import Overview from './Overview'
import DetailView from './DetailView'
import "./index.css";
import { Router, Route, IndexRoute, hashHistory } from 'react-router'
const routes = (
<Router history={hashHistory}>
<Route path="/" component={App}>
<IndexRoute component={Overview} />
<Route path="detail/:id" component={DetailView} />
</Route>
</Router>
)
ReactDOM.render(
routes,
document.getElementById('root')
);
App.js
import React, {Component} from "react"
import "./App.css"
export default class App extends Component {
render() {
return (
<div className="App">
{this.props.children}
</div>
)
}
}
Overview.js - Note the ID on the SharedElement
import React, { Component } from 'react'
import './Overview.css'
import items from './items' // Simple array containing objects like {title: '...'}
import { hashHistory } from 'react-router'
import SharedElement from './SharedElement'
export default class Overview extends Component {
showDetail = (e, id) => {
e.preventDefault()
hashHistory.push(`/detail/${id}`)
}
render() {
return (
<div className="Overview">
{items.map((item, index) => {
return (
<div className="ItemOuter" key={`outer-${index}`}>
<SharedElement id={`item-${index}`}>
<a
className="Item"
key={`overview-item`}
onClick={e => this.showDetail(e, index + 1)}
>
<div className="Item-image">
<img src={require(`./img/${index + 1}.jpg`)} alt=""/>
</div>
{item.title}
</a>
</SharedElement>
</div>
)
})}
</div>
)
}
}
DetailView.js - Note the ID on the SharedElement
import React, { Component } from 'react'
import './DetailItem.css'
import items from './items'
import { hashHistory } from 'react-router'
import SharedElement from './SharedElement'
export default class DetailView extends Component {
getItem = () => {
return items[this.props.params.id - 1]
}
showHome = e => {
e.preventDefault()
hashHistory.push(`/`)
}
render() {
const item = this.getItem()
return (
<div className="DetailItemOuter">
<SharedElement id={`item-${this.props.params.id - 1}`}>
<div className="DetailItem" onClick={this.showHome}>
<div className="DetailItem-image">
<img src={require(`./img/${this.props.params.id}.jpg`)} alt=""/>
</div>
Full title: {item.title}
</div>
</SharedElement>
</div>
)
}
}
SharedElement.js
import React, { Component, PropTypes, cloneElement } from 'react'
import { findDOMNode } from 'react-dom'
import TweenMax, { Power3 } from 'gsap'
export default class SharedElement extends Component {
static Store = {}
element = null
static props = {
id: PropTypes.string.isRequired,
children: PropTypes.element.isRequired,
duration: PropTypes.number,
delay: PropTypes.number,
keepPosition: PropTypes.bool,
}
static defaultProps = {
duration: 0.4,
delay: 0,
keepPosition: false,
}
storeNewPosition(rect) {
SharedElement.Store[this.props.id] = rect
}
componentDidMount() {
// Figure out the position of the new element
const node = findDOMNode(this.element)
const rect = node.getBoundingClientRect()
const newPosition = {
width: rect.width,
height: rect.height,
}
if ( ! this.props.keepPosition) {
newPosition.top = rect.top
newPosition.left = rect.left
}
if (SharedElement.Store.hasOwnProperty(this.props.id)) {
// Element was already mounted, animate
const oldPosition = SharedElement.Store[this.props.id]
TweenMax.fromTo(node, this.props.duration, oldPosition, {
...newPosition,
ease: Power3.easeInOut,
delay: this.props.delay,
onComplete: () => this.storeNewPosition(newPosition)
})
}
else {
setTimeout(() => { // Fix for 'rect' having wrong dimensions
this.storeNewPosition(newPosition)
}, 50)
}
}
render() {
return cloneElement(this.props.children, {
...this.props.children.props,
ref: element => this.element = element,
style: {...this.props.children.props.style || {}, position: 'absolute'},
})
}
}
I actually had a similar problem, where I had a search bar and wanted it to move and wrap to a different size and place on a specific route (like a general search in the navbar and a dedicated search page). For that reason, I created a component very similar to SharedElement above.
The component expects as props, a singularKey and a singularPriority and than you render the component in serval places, but the component will only render the highest priority and animate to it.
The component is on npm as react-singular-compoment
And here is the GitHub page for the docs.

Resources