undefined is not an object (evaluating 'navigation.navigate') - react-native

I am trying to navigate from one screen to other screen inside tabbar in react native.
But, I am getting following error
ButtonClickCheckFunction = () => {
const { navigation } = this.props;
navigation.navigate('detailsScreen', { detailsScreen: jsonData });
}
Any suggestions?
For main screens, In tab bar we have created stack,
const AppStack = createAppContainer(createDrawerNavigator({
Dashboard: {
screen: ProfileStack,
},
Connect: {
screen: Connect,
},
screen1: {
screen: Screen1,
}
});
But, In Dashboard screen we are showing tabbar. I am working with tab2. So, From tab2, I have details screen. In that details screen I have to show navigation bar with back button arrow like custom image.
So, How to fix this?

If you post more code, we'll be able to better answer your question.
From the error message though, it seems like you're not properly creating the component so that the navigation property is set. You'll need to make sure to wrap the component using the withNavigation higher order component.
export default withNavigation(MyComponent);

Related

React Native and React Navigation — How to get screen title to show in header and bottom tab navigator to also show

I am teaching myself React Native and building a fairly simple app,irMobile.
I've set up each screen with (using the About screen as an example)
static navigationOptions = () => ({
title: 'About'
})
and in my app's main component
const MainNavigator = createBottomTabNavigator({ About })
const StackNavigator = createStackNavigator({ MainNavigator })
const AppContainer = createAppContainer(StackNavigator)
then in the component itself
render() {
return (
<View style={styles.container}>
<AppContainer />
</View>
)
}
My screens render with a nice nav bar at the bottom but I don't get any titles in the header, just an empty space.
I've gone through the docs several times looking to see what I have missed and I'm stumped.
If I use the inspector in the iOS simulator I can select the header and it shows it to be a View at x: 0, y: 44 with width: 375 and height: 43.7, so the thing is there I just can't see it.
I've tried setting a headerStyle to { backgroundColor: 'red' } to see if I can at least see that, but no.
However, if I change the StackNavigator to put the About screen in there along with the MainNavigator as follows:
const StackNavigator = createStackNavigator({ About, MainNavigator })
Then I get my header showing up as expected, but the bottom tab bar no longer shows.
So that's confusing.
The docs are a bit vague on how to get both a header and a bottom tab navigator into the same app. Clearly, being a bit of a React Native noob here, I am missing something really obvious and simple.
What am I failing to understand and how do I fix this?
Source code at github.com/davesag/irMobile.
By setting navigationOptions inside the component, you apply it to the navigation element that is calling the component.
So in your case, the title you define in About applies to the bottom tab, and not to the screen as you would like to.
Rather than setting navigationOptions as a static property inside the component, you need to define it directly when creating the stack navigation.
In addition to this, I think you want to nest the stack inside the bottom tab navigation, not the other way around. By doing so, you can have a different title for each screen.
Here is an example:
const AboutStack = createStackNavigator({ About: { screen: About, navigationOptions: { title: 'About Title' } } });
const CreditStack = createStackNavigator({ Credit: { screen: Credit, navigationOptions: { title: 'Credit Title' } } });
const MainNavigator = createBottomTabNavigator({
About: { screen: AboutStack, navigationOptions: { title: 'About Label' } },
Credit: { screen: CreditStack, navigationOptions: { title: 'Credit Label' } },
});
const AppContainer = createAppContainer(MainNavigator);
Like this, the header title will be "About Title" and the tab label "About Label".
Okay I have worked it out.
The trick is to use getActiveChildNavigationOptions.
So now my code looks like
const navBar = useStorybook({ Balances, Settings, About })
const MainNavigator = createBottomTabNavigator(navBar, {
navigationOptions: ({ navigation, screenProps }) =>
getActiveChildNavigationOptions(navigation, screenProps)
})
const StackNavigator = createStackNavigator({ MainNavigator })
const AppContainer = createAppContainer(StackNavigator)
As #Remeus pointed out, the titles in my actual screen components were only making it to the MainNavigator and not accessible by the StackNavigator.
Rather than invert my stack however and create a StackNavigator for each tab, it seems to me to be cleaner to leverage getActiveChildNavigationOptions to grab the screen components' title (and other) navigationOptions.
This works perfectly.

React Navigation - goBack() is automatically invoked for stack navigator screen

I have 3 stack navigator screens (Home, Item List, Item Detail -> same order) inside drawer navigator and all three screens are hooked up to redux store with connect() helper.
When I do navigate('ItemDetail') from ItemList, it navigates to the screen and immediately comes back to ItemList screen. I am not sure why.
Following is my navigation structure -
const AppStack = createStackNavigator(
{
Home: {
screen: HomeScreen
},
ItemList: {
screen: ItemListScreen
},
ItemDetail: {
screen: ItemDetailScreen
}
},
{
initialRouteName: 'Home'
}
);
const DrawerNav = createDrawerNavigator(
{
DrawerApp: AppStack
},
{
drawerPosition: 'right'
}
);
const SwitchStack = createSwitchNavigator(
{
Loading: Loading,
Auth: AuthStack,
App: DrawerNav
},
{
initialRouteName: 'Loading'
}
);
This is how my each navigation screen component looks -
export class ProviderListScreen extends Component {
render() {
const { navigation } = this.props;
// ItemList is hooked up to Redux via connect() helper
return <ItemList navigation={navigation} />;
}
On my ItemDetail component, I get the Item data through route params from ItemList screen and I also dispatch an action (To reset some part of the store state) in component did mount. As soon as I do that, previous screen (ItemList) is automatically rendered.
Inside item detail, I make API call to create booking for that item and the booking object is managed by redux. Once I land on the ItemDetail, I reset the booking object for new booking data.
Here is the snippet of ItemDetail's componentDidMount -
componentDidMount() {
this.props.resetItembooking();
}
I am not sure what is causing this behaviour. If I remove the ItemList screen and jump directly to ItemDetail screen from HomeScreen, this issue does not occur.
Any help is appreciated.
I had the exact same problem however I tried the answer given in the original post comments sections given by Awadhoot but this did not work for me.
For anyone still trying to solve this issue, ensure you do not have any recurring intervals setup. Therefore you should always clear intervals before navigating away:
clearInterval(this.intervalId);
In react-navigation 5 you can use the useIsFocused hook for that:
import { useIsFocused } from '#react-navigation/native';
// ...
function Profile() {
const isFocused = useIsFocused();
return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
}
From the docs: https://reactnavigation.org/docs/use-is-focused/

react navigation splash screen to login screen

I have created a splash screen and a login screen. I would like that after 2 second my screen goes splash to log in but it's showing: undefined is not an object(evaluating
'_this.props.navigation.push ')
In this project I am using react-navigation
componentWillMount(){
setTimeout(
() => {
this.props.navigation.push({
screen:'smartbill.login',
title:'LOGIN SCREEN'
});
}
, 1000);
}
Hope you have created a stack navigator
const App = createStackNavigator({
Splash: { screen: SplashScreen },
Login: { screen: LoginScreen },
});
In Splash Screen
setTimeout(()=> {
navigate('Login', { name: 'Jane' })
},1000);
Below is an example of me navigating to a home screen from splash
setTimeout(
()=> {
this.props.navigation.navigate("Home");
},1000
);
For Navigation you should use StackNavigator in react-native thats the proper method
Where did you get this this.props.navigation.push thats not proper.
Or
I have an excepted answer in the below question.
How to navigate from splash screen to login screen in react native?
There is a google drive link on it from where you can download a sample project, its a simple app figure it out from the sample app how you should set up the App.js.
I suggest You should use StackNavigator for navigation its the best method to follow in my app App.js is configured using StackNavigator.

How to invoke App.js from inner component ReactNative?

I'm using StackNavigator to load a Tabbar created with react-native-tab-navigator in App.js. I have a view inside Tabbar. How can I navigate back to App.js from that view?
App.js
import { StackNavigator } from 'react-navigation';
const SigninSignup = StackNavigator({
Signup: { screen: Signup },
Signin: { screen: Signin },
});
render() {
if (this.state.condition) {
return (<Tabbar />);
} else {
return (<SigninSignup />);
}
}
Myview.js (It is inside Tabbar)
How can I go back to App.js and load SigninSignup ?
I have tried
const { navigate } = this.props.navigation;
navigate('Signin', {});
But getting ERROR undefined is not an object (evaluating 'this.props.navigation')
Your navigation hierarchy starts with the SigninSignup navigator.
Since your component is rendering either the navigator or your tab bar according to this.state.condition, you can't just navigate to the other screen.
You con solve this be either moving the tab bar and the SigninSignup navigator into a new root navigator and use that to navigate between everything, or by providing a function to Tabbar that would change the value of condition:
<Tabbar onSomething={() => this.setState({condition: !this.state.condition})} />

how to navigate to another screen in react native when fetch is done

I'm new in React Native and trying create my first app. So I have a question:
I got 2 screens (using react-navigation). At first screen there is a render of app logo with spinner(from native-base) and fetch to the server at the same time. And I need to navigate to another screen only when fetch is over and responce is handled. All I found at react-navigation docs is a solution with button, but it's not my case. Also I don't want to use ActivityIndicatorIOS (app should be correct for Android).
Please help me understand what should I do?
Thanks a lot!
Just call the navigate function in then callback of the fetch or handle error appropriately in catch.
Every screen in react-navigation gets the navigation prop. You can use the navigate function to navigate to any screen. Something like this
class FirstScreen extends React.Component {
static navigationOptions = {
title: 'First',
}
componentDidMount(){
const {navigate} = this.props.navigation;
navigate('Second');
fetch('http://apiserver').then( (response) => {
navigate('Second');
});
}
render() {
return (
<AppLogo />
);
}
}
const AppNavigator = StackNavigator({
First: {
screen: FirstScreen,
},
Second: {
screen: SecondScreen,
},
});