How to Resolve "Undefined Is Not an Object (Evaluating 'this.props.navigation')"
Quick answer
A component tries to use this.props.navigation (or its Hooks equivalent) to navigate to another screen, but the navigation object simply isn't there. This...
A component tries to use this.props.navigation (or its Hooks equivalent) to navigate to another screen, but the navigation object simply isn't there. This means the component isn't receiving navigation the way it expects — usually because it isn't actually registered as a screen in your navigator, or it's a nested component that needed the prop passed down explicitly.
The Problem
Tapping a button meant to navigate crashes the app instead:
undefined is not an object (evaluating 'this.props.navigation.navigate')
In a class component, this usually happens inside an event handler:
class ProfileScreen extends React.Component {
goToSettings = () => {
this.props.navigation.navigate('Settings'); // crashes here
};
...
}
With Hooks, the equivalent error appears when the useNavigation hook wasn't actually available in the right context:
TypeError: Cannot read property 'navigate' of undefined
Why It Happens
React Navigation automatically injects the navigation prop only into components that are directly registered as a screen within a navigator (a Stack.Screen, Tab.Screen, etc.). Any component rendered as a child inside that screen — rather than being a screen itself — does not automatically receive it. This error shows up in a few specific patterns:
- A child component tries to use
this.props.navigationwithout it having been explicitly passed down from its parent screen, since only the direct screen component gets it automatically. - A component is rendered outside the navigator entirely — for example, in a modal, a portal, or a component tree not mounted as part of the navigation stack.
- Using the
useNavigation()hook outside of the React Navigation context — the hook only works within a component tree that's actually wrapped by aNavigationContainer. - Testing a screen component in isolation (a unit test, or Storybook) without providing a mock navigation object, since outside of an actual running app, nothing is there to inject it.
The Fix
For a child component that genuinely needs to navigate, pass the navigation prop down explicitly from its parent screen, which does have automatic access to it:
function ProfileScreen({navigation}) {
return (
<View>
<ProfileHeader navigation={navigation} />
</View>
);
}
function ProfileHeader({navigation}) {
return (
<Button title="Settings" onPress={() => navigation.navigate('Settings')} />
);
}
A cleaner, more modern alternative — especially useful for deeply nested components where manually threading the prop through several layers gets tedious — is using the useNavigation hook directly inside the child component, which reaches into React Navigation's context regardless of how deeply nested the component is:
import {useNavigation} from '@react-navigation/native';
function ProfileHeader() {
const navigation = useNavigation();
return (
<Button title="Settings" onPress={() => navigation.navigate('Settings')} />
);
}
This works as long as ProfileHeader is rendered somewhere inside the tree wrapped by NavigationContainer, regardless of whether it's a direct screen or a deeply nested child component.
For a class component that needs the equivalent behavior, use the withNavigation higher-order component (older React Navigation versions) or convert to a functional component to use the hook directly, since Hooks are the currently recommended, actively maintained approach:
import {useNavigation} from '@react-navigation/native';
function withNavigation(Component) {
return function WrappedComponent(props) {
const navigation = useNavigation();
return <Component {...props} navigation={navigation} />;
};
}
class ProfileHeader extends React.Component {
render() {
return <Button title="Settings" onPress={() => this.props.navigation.navigate('Settings')} />;
}
}
export default withNavigation(ProfileHeader);
Still Not Working?
If the error occurs on what you believe is a properly registered screen component, double-check that it's actually being rendered through the navigator rather than imported and rendered directly somewhere else in your code (a common mistake when a screen component is reused as a regular component elsewhere, expecting props that only the navigator provides):
// This does NOT provide navigation automatically:
import ProfileScreen from './screens/ProfileScreen';
function SomeOtherComponent() {
return <ProfileScreen />; // no navigation prop injected here
}
If you genuinely need to render a screen component outside of the navigator (for a preview, a test, or an embedded use case), pass a manually constructed navigation object matching the shape your component expects, or better, extract the navigation-dependent logic into a separate component that only screens use, keeping the reusable inner component free of any direct navigation dependency at all.