React Navigation stack navigator doesn't work - react-native

I used stackNavigator 2 in one of my projects as follows.
import { StackNavigator } from "react-navigation";
import {
LoginScreen,
TechStackScreen
} from '../screens';
// Public routes
export const PublicRoutes = StackNavigator({
login: { screen: LoginScreen}
});
// Secured routes
export const SecuredRoutes = StackNavigator({
techStack: { screen: TechStackScreen}
});
But when I tried to use it with version 3+ this doesn't work. Can anyone give me sample code of how to use stacknavigation 3+ like this?

You need to use createAppContainer on your root navigator. This was a breaking change introduced in v3
Also StackNavigator has been replaced by createStackNavigator
Here is a simple example of the usage.
App.js
import React, {Component} from 'react';
import AppContainer from './MainNavigation';
export default class App extends React.Component {
render() {
return (
<AppContainer />
)
}
}
MainNavigation.js
import Screen1 from './Screen1';
import Screen2 from './Screen2';
import { createStackNavigator, createAppContainer } from 'react-navigation';
const screens = {
Screen1: {
screen: Screen1
},
Screen2: {
screen: Screen2
}
}
const config = {
headerMode: 'none',
initialRouteName: 'Screen1'
}
const MainNavigator = createStackNavigator(screens,config);
export default createAppContainer(MainNavigator);

You should import and use createStackNavigator, here is the docs https://reactnavigation.org/docs/en/stack-navigator.html
Just need a small change on your code
// Public routes
export const PublicRoutes = createStackNavigator({
login: { screen: LoginScreen}
});
// Secured routes
export const SecuredRoutes = createStackNavigator({
techStack: { screen: TechStackScreen}
});

Well, if you are using StackNavigator, like this:
// Inside "App.js"
render() {
return (
<NavigationContainer >
<Stack.Navigator >
<Stack.Screen name='Details'
component={ Details } />
</Stack.Navigator >
</NavigationContainer >
)
}
You can use the navigation via accessing properties available with each component:
// Inside "Details" Component
export default class Details extends React.Component {
render() {
const { navigate } = this.props.navigation
return (
<Button title='Goto Component' onPress={ () => navigate( 'SomeOtherComponent' ) }/>
)
}
}

Related

undefined is not an object (evaluating '(0 _reactnavigation.DrawerNavigator)')

I have created customized sidebar and have 5 to 6 screens. I am using NativeBase and want to open Sidebar with DrawerNavigator option but when I applied following code it was getting issue.
Drawer Navigator code
import React, { Component } from "react";
import WelcomeScreen from './screens/WelcomeScreen';
import ContactScreen from './screens/ContactScreen';
import DepartmentScreen from './screens/DepartmentScreen';
import EmailServiceScreen from './screens/EmailServiceScreen';
import MoreScreen from './screens/MoreScreen';
import SideBar from "./SideBar.js";
import { DrawerNavigator } from "react-navigation";
const SidebarNavigator = DrawerNavigator(
{
Home: { screen: WelcomeScreen },
Contact: { screen: ContactScreen },
Department: { screen: DepartmentScreen },
EmailService: { screen: EmailServiceScreen },
More: { screen: MoreScreen }
},
{
contentComponent: props => <SideBar {...props} />
}
);
export default SidebarNavigator;
Calling them in APP.Js as propos. See following code from APP.JS
import SidebarNavigator from './src/SidebarNavigator';
class App extends Component {
render() {
const store = createStore(reducers, {}, applyMiddleware(ReduxThunk));
return (
<Provider store={createStore(reducers)}>
<Root>
<Router /> // It's a stack navigator which is working fine
<SidebarNavigator />
</Root>
</Provider>
);
}
}
console.disableYellowBox = true;
export default App;
The error here is that you are using DrawerNavigation instead of createDrawerNavigator.
Just do those changes and you should be good
import { createDrawerNavigator } from "react-navigation";
...
const SidebarNavigator = createDrawerNavigator( ... )
Source: https://reactnavigation.org/docs/en/drawer-navigator.html
You can try this code
You can use createDrawerNavigator and createAppContainer
import { createDrawerNavigator, createAppContainer } from "react-navigation";
...
const SidebarNavigator = createDrawerNavigator( ... )
const AppContainer = createAppContainer(SidebarNavigator);
// Now AppContainer is the main component for React to render
export default AppContainer;

Can't open Drawer react native

I created createDrawerNavigator. But when call "props.navigation.dispatch(DrawerActions.openDrawer())" nothing show. Here is my code.
MenuNavigator.js
import { createDrawerNavigator } from "react-navigation";
import Login from "../screens/auth/Login"
import ForgotPassword from "../screens/auth/ForgotPassword"
import SignUp from "../screens/auth/SignUp";
const MenuNavigator = createDrawerNavigator({
//Drawer Optons and indexing
ForgotPassword: ForgotPassword,
SignUp: SignUp,
},
{
contentOptions: {
activeTintColor: '#e91e63',
},
}
);
export default MenuNavigator;
AppNavigator
import { createStackNavigator, createAppContainer } from "react-navigation";
import StackNavigatorMain from "./StackNavigatorMain"
import MenuNavigator from "./MenuNavigator"
const AppNavigator = createStackNavigator(
{
StackNavigatorMain: StackNavigatorMain,
MenuNavigator: MenuNavigator
},
{
headerMode: "none",
navigationOptions: {
headerVisible: false
},
initialRouteName: "StackNavigatorMain"
}
);
export default createAppContainer(AppNavigator);
Call openDrawer
onLoginClicked = () => {
props.navigation.dispatch(DrawerActions.openDrawer());
}
First get the reference of the navigator from top level component like this:
const AppContainer = createAppContainer(AppNavigator);
return <AppContainer ref={navigatorRef => Navigation.setTopLevelNavigator(navigatorRef)} />;
In Navigation.js file you need to set a global variable for navigator reference :
let _navigator;
function setTopLevelNavigator(navigatorRef) {
_navigator = navigatorRef;
}
Then create function there like this:
function openDrawer() {
_navigator.dispatch(DrawerActions.openDrawer())
}
Do not forget to import them:
import { DrawerActions } from 'react-navigation';
After that export them from Navigation.js file:
export default {
setTopLevelNavigator,
openDrawer,
}
AFAIK Opening drawer from React-navigation v3 is called like this piece of code
this.props.navigation.openDrawer();
EDIT:
I tried to minimally replicate this using react-navigation v3
https://snack.expo.io/#keysl183/basic-drawer-v3

Cannot access redux props inside react-navigation v3 tab navigator (getting error this.props.<function_name> is not a function)

I am having trouble connecting the tab navigator (from React-Navigation v3) to the redux provider.
So this is how my react-navigation and redux is configured:
app/
/react-redux provider
/app-container (this is the AppContainer of the main SwitchNavigator)
/welcome-screen
/login-screen
/register-screen
/home-navigator (this is the TabNavigator that is inside the SwitchNavigator)
Home navigator holds the screens to which user is directed to when he logs-in. In the first 3 screends (welcome, login and register) I can access the functions that are "connected" from redux to the screen through standard mapDispatchToProps.
This is the app component:
/**
* Entry point for the app
*/
import React, { Component } from "react";
// redux
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import reduxThunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import main_app_reducer from "./modules/core/reducers/main_app_reducer";
// create redux store
const create_store = composeWithDevTools(applyMiddleware(reduxThunk))(createStore);
export const store = create_store(main_app_reducer);
// navigation
import AppContainer from "./modules/core/components/AppNavigator";
import { configure_axios } from "./helpers/axios_config";
configure_axios();
class App extends Component {
render() {
return (
<Provider store={store}>
<AppContainer />
</Provider>
);
}
}
export default App;
And then, from there we go to AppContainer:
/**
* this components ensures app navigation so that user can jump from one screen to another
*/
// navigation
import { createSwitchNavigator, createAppContainer } from "react-navigation";
// screens
import WelcomeScreen from "../screens/WelcomeScreen";
import LoginScreen from "../../auth/screens/LoginScreen";
import RegisterScreen from "../../auth/screens/RegisterScreen";
import HomeNavigator from "./HomeNavigator";
const AppSwitchNavigator = createSwitchNavigator({
// for users that are not logged in yet
Welcome: { screen: WelcomeScreen },
Login: { screen: LoginScreen },
Register: { screen: RegisterScreen },
// for logged in users
HomeNavigator: { screen: HomeNavigator },
});
const AppContainer = createAppContainer(AppSwitchNavigator);
export default AppContainer;
All of the code above works perfectly with no errors, the problem occurs inside the HomeNavigator component that you see below.
This is the HomeNavigator component:
import { createBottomTabNavigator } from "react-navigation";
import { HomeScreen } from "../screens/HomeScreen";
import { DashboardScreen } from "../screens/DashboardScreen";
const HomeNavigator = createBottomTabNavigator(
{
Home: { screen: HomeScreen },
Dashboard: { screen: DashboardScreen },
},
{
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
return {
headerTitle: routeName,
};
},
},
);
export default HomeNavigator;
NONE of the screens inside the HomeNavigator are connected to Redux altough they are defined THE SAME WAY as the screens inside AppContainer file. For comparison let's see Login screen from AppContainer and Home screen from HomeNavigator:
LoginScreen:
import React, { Component } from "react";
import { View, Text } from "react-native";
import { connect } from "react-redux";
import { get_user_servers } from "../actions/core_actions";
export class LoginScreen extends Component {
componentDidMount() {
this.props.get_user_servers(); // this function works absolutely fine
}
render() {
return (
<View>
<Text> LoginScreen </Text>
</View>
);
}
}
const mapStateToProps = (state) => ({});
const mapDispatchToProps = { get_user_servers };
export default connect(
mapStateToProps,
mapDispatchToProps,
)(LoginScreen);
HomeScreen:
import React, { Component } from "react";
import { View, Text } from "react-native";
import { connect } from "react-redux";
import { get_user_servers } from "../actions/core_actions";
export class HomeScreen extends Component {
componentDidMount() {
this.props.get_user_servers();
// the same function as in LoginScreen but here the function does not work
// I'm getting an error = TypeError: this.props.get_user_servers is not a function (see picture below)
}
render() {
return (
<View>
<Text> HomeScreen </Text>
</View>
);
}
}
const mapStateToProps = (state) => ({});
const mapDispatchToProps = { get_user_servers };
export default connect(
mapStateToProps,
mapDispatchToProps,
)(HomeScreen);
That function (get_user_servers) is defined properly and it works fine in LoginScreen.
thanks everyone who took their time to help me, in the end it was my mistake that I overlooked. If you check out the third code-block from this question you can see that I import my components like this:
import { HomeScreen } from "../screens/HomeScreen";
import { DashboardScreen } from "../screens/DashboardScreen";
Which is wrong, I changed that to:
import HomeScreen from "../screens/HomeScreen";
import DashboardScreen from "../screens/DashboardScreen";
And now everything works fine, thanks again :)
Assuming it's the same function you're importing, please could you try to check your import of get_user_servers function from both screen : LoginScreen and HomeScreen. According to your code it look like LoginScreen ("../../auth/screens/LoginScreen") and HomeScreen ("../screens/HomeScreen") are not in the same path.
As asked above, could check the path of the files, or post it so we can help. Also could you open the remote debugger, and inside the componentWillMount you can put:
console.log(this.props)
to check if the HomeScreen is geting the function inside props.

Using react-navigation 3.* how to navigate from screen to same level BottomTabNavigator?

I got react native app with such structure:
./App.js
./screens/AppNavigator.js
./screens/SignInScreen.js
./screens/HomeScreen.js
./screens/FavoritesScreen.js
App.js:
import { createAppContainer } from "react-navigation";
import AppNavigator from './screens/AppNavigator';
const AppContainer = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return (
<View>
<AppContainer/>
</View>
);
}
}
screens/AppNavigator.js:
import { createSwitchNavigator, createBottomTabNavigator } from 'react-navigation';
import SignInScreen from './SignInScreen';
import HomeScreen from './HomeScreen';
import FavoritesScreen from './FavoritesScreen';
const AppBottomTabNavigator = createBottomTabNavigator({
Home: {
screen: HomeScreen
},
Favorites: {
screen: FavoritesScreen
}
},
{
initialRouteName: 'Home',
});
export default createSwitchNavigator(
{
App: AppBottomTabNavigator,
Auth: SignInScreen
},
{
initialRouteName: 'SignInScreen',
}
);
screens/SignInScreen.js:
export default class SignInScreen extends React.Component {
render() {
return (
<View>
<Button title="Continue w/o sing in..." onPress={this.toApp} />
</View>
);
}
toApp = () => {
this.props.navigation.navigate('App'); // from here I try to navigate to Home screen
};
}
And when I try to navigate to HomeScreen from SignInScreen I see white screen instead of HomeScreen, though all other navigation works well.
The problem do not occur if in screens/AppNavigator.js I change createBottomTabNavigator to createSwitchNavigator, got no idea why. A problem also do not appear if in screens/AppNavigator.js I navigate direct to HomeScreen or FavoritesScreen instead of AppBottomTabNavigator.
I found this thread on github, but, as I understand, it's not related for me, because both AppBottomTabNavigator and SignInScreen are childs of AppNavigator.
So, what is weong with my code?
The problem is in de App.js. For some reason you can't put a BottomTabNavitation inside a View Component, so remove. Like this:
export default class App extends React.Component {
render() {
return (
<AppContainer/>
);
}
}
You should also change the parameter initialRoutName in createSwitchNavigator. You have to put the routName, in this case Auth.
export default createSwitchNavigator(
{
App: AppBottomTabNavigator,
Auth: SignInScreen
},
{
initialRouteName: 'Auth',
}
);

React-native with react-navigation: header not showing in screen

I do have a simple React-native app, using react-navigation for navigation. My issue is that for one of the screens the header and title is not showing, even though it is set in navigationOptions:
main.js:
import React from "react";
import { View, Text } from "react-native";
import {
createDrawerNavigator,
createAppContainer,
createStackNavigator
} from "react-navigation";
import ArticleList from "./screens/ArticleList";
import ArticleList2 from "./screens/ArticeList2";
import ArticleWebView from "./screens/ArticleWebView";
// create the Navigator to be used
const Stack = createStackNavigator({
ArticleList: { screen: ArticleList },
ArticleWebView: { screen: ArticleWebView }
});
const Drawer = createDrawerNavigator(
{
Stack: { screen: Stack },
ArticleList2: { screen: ArticleList2 }
},
{
initialRouteName: "Stack"
}
);
// The container for the navigator
const AppContainer = createAppContainer(Drawer);
class App extends React.Component {
render() {
return <AppContainer />;
}
}
export default App;
The ArticleList2 is a very simple component:
import React from "react";
import { View, Text } from "react-native";
import ArticleListComponent from "../components/ArticleListComponent";
class ArticleList2 extends React.Component {
static navigationOptions = {
title: 'Link2'
};
render() {
return (
<View>
<Text>LIst2</Text>
</View>
);
}
}
export default ArticleList2;
However, the title and header are not rendered in the app. Could anybody help please?
DrawerNavigator does not include a header. In order to create a header inside of ArticleList2 you will have to create a new StackNavigator for the component.
You have to think about and plan out the navigation flow of your app.
The Drawer section of the React Navigation documentation is a little lacking, but you can use the same principle as described in the Tab section
A stack navigator for each tab
const ArticleList2Stack = createStackNavigator({
ArticleList2: { screen: ArticleList2 }
});
const Drawer = createDrawerNavigator(
{
Stack: { screen: Stack },
ArticleList2: { screen: ArticleList2Stack }
},
{
initialRouteName: "Stack"
}
);