How can I create createDrawerNavigator inside createStackNavigator in React native? - react-native

I'm using react-navigation v3 for react native app.
When I createDrawerNavigator inside createStackNavigator I can't openDrawer but if I createDrawerNavigator in root navigator I can open it.
Here is my code. Anyone have a solution for me?
AppNavigator.js
const AppNavigator = createSwitchNavigator(
{
StackNavigatorMain: StackNavigatorMain,
StackMenu: StackMenu
},
{
headerMode: "null",
navigationOptions: {
headerVisible: false
},
initialRouteName: "StackNavigatorMain"
}
);
export default createAppContainer(AppNavigator);
StackNavigatorMain.js
const StackNavigatorMain = createStackNavigator(
{
routeHome: Home,
routeLogin: Login,
routeForgotPassword: ForgotPassword,
routeSignUp: SignUp,
},
{
headerMode: "none",
initialRouteName: strings.routeHome,
}
)
export default StackNavigatorMain
StackMenu.js
const StackMenu = createStackNavigator({
//Drawer Optons and indexing
MenuNavigator: MenuNavigator,
},
{
headerMode: "null",
navigationOptions: {
headerVisible: false
},
}
);
export default StackMenu;
MenuNavigator.js
const MenuNavigator = createDrawerNavigator({
//Drawer Optons and indexing
Setting: Setting
},
{
drawerWidth: responsiveWidth(180),
overlayColor: 'transparent',
// drawerLockMode: 'locked-open',
contentComponent: AppSideMenu
}
);
export default MenuNavigator;
index.js
export default class App extends Component {
render() {
return (
<AppNavigator/>
);
};
}
Call open drawer onPress button in Component screen
onClicked = () => {
// props.navigation.openDrawer();
props.navigation.dispatch(DrawerActions.openDrawer());
}

Related

how to use provider for redux to connect it with map state

i have build an full stack drawer and tab navigators in my app.js and now how can i use provider of redux to connect in whole app should i create an new screen and move all components of app.js to that or do something in app.js
const SplashScreen = createStackNavigator({
ScreenWith:{
screen:ScreenWith,
navigationOptions:{
headerTitle:'Logo1',
},
},
});
const HomeStack = createStackNavigator({
Homeview: {
screen: Homeview,
navigationOptions: {
headerTitle: 'Home',
},
},
Beauty: {
screen: Beauty,
navigationOptions: {
headerTitle: 'Beauty',
},
},
ContentPage:{
screen:ContentPage,
navigationOptions:{
headerTitle:'Authenticated',
},
},
Yourcart:{
screen:Yourcart,
navigationOptions:{
headerTitle:'Your Cart',
},
},
SignIn: {
screen: SignIn,
navigationOptions: {
headerTitle: 'SignIn',
},
},
Signup:{
screen:Signup,
navigationOptions:{
headerTitle:'Registered',
},
},
Forgotemail:{
screen:Forgotemail,
navigationOptions:{
headerTitle:'Forgotemail',
}
},
});
const MainTabs = createBottomTabNavigator({
Home: {
screen: HomeStack,
},
Account: {
screen: Account,
},
},
});
const MainDrawer = createDrawerNavigator({
MainTabs : MainTabs,
},{
contentComponent:props =><Drawescreen {...props}/>
});
const AppModalStack = createStackNavigator(
{
App: MainDrawer,
Screentest: Homeview,
},
{
mode: 'modal',
headerMode: 'none',
}
);
const App = createSwitchNavigator({
SplashScreen: {
screen: SplashScreen,
},
App: {
screen: AppModalStack,
},
});
export default createAppContainer(App);
this is my app.js now where i should i add provider to connect with redux ?
Assume that you have export your Container as App
Assume that you have created a class called Main for import your Container App file
This is how you add Provider to your app:
import React from 'react';
import App from '../App'; //Import your app Container
import {Provider} from 'react-redux'; //Import Provider
import store from '../redux/store/store'; //Import your store
const reduxStore = store(); //create redux store
class Main extends React.Component {
render() {
return (
<Provider store={reduxStore}>
<AppContainer />
</Provider>
);
}
}
export default Main;

createDrawerNavigator Is Not Working React Native

I tried lots of things to open drawer but nothing works for me. I do not understand how to combine navigators like I have, one is createStackNavigator and second is createDrawerNavigator. Please check my code if anything goes wrong so let me know otherwise provide me a link or code to implement. thanks
App.js
import React, { Component } from 'react';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import LoginScreen from './src/screens/LoginScreen';
import SignupScreen from './src/screens/SignupScreen';
import DashboardScreen from './src/screens/DashboardScreen';
import CaseListingScreen from './src/screens/CaseListingScreen';
import { createDrawerNavigator, DrawerItems } from "react-navigation-drawer";
import SideBar from './src/SideBar';
const DrawerNavigator = createDrawerNavigator({
Home: {
screen: DashboardScreen,
},
Cases: {
screen: CaseListingScreen,
navigationOptions: {
header: null
}
}
},
{
initialRouteName: 'Home',
}
);
const AppNavigator = createStackNavigator({
Dashboard: {
screen: DashboardScreen,
navigationOptions: {
header: null
}
},
Cases: {
screen: CaseListingScreen,
navigationOptions: {
header: null
}
},
Login: {
screen: LoginScreen,
navigationOptions: {
header: null
}
},
Signup: {
screen: SignupScreen,
navigationOptions: {
header: null
}
}
});
export default createAppContainer(AppNavigator, DrawerNavigator);
DashboardScreen.js
export default class DashboardScreen extends Component {
static navigationOption = {
drawerLabel: 'Home'
}
render() {
return (
<Container>
<Appbar.Header theme={{ colors: { primary: '#b33f3f' } }}>
<Appbar.Action icon="menu" onPress={() => this.props.navigation.navigate('DrawerOpen')} />
<Appbar.Content
title="Manage My Case"
subtitle="Dashboard"
/>
</Appbar.Header>
</Container>
);
}
}
In your export default createAppContainer(AppNavigator, DrawerNavigator); , you should have the drawerNavigator as the app container and not along with App navigator.
createAppContainer contains only 1 arguement , so pass DrawerNavigator in the app container, and if you want to use the stackNavigator inside the drawer navigator just create the drawernavigator as ,
const AppNavigator = createStackNavigator({
Dashboard: {
screen: DashboardScreen,
navigationOptions: {
header: null
}
},
Cases: {
screen: CaseListingScreen,
navigationOptions: {
header: null
}
},
Login: {
screen: LoginScreen,
navigationOptions: {
header: null
}
},
Signup: {
screen: SignupScreen,
navigationOptions: {
header: null
}
}
});
const DrawerNavigator = createDrawerNavigator({
Home: {
screen: DashboardScreen,
},
Cases: {
screen: CaseListingScreen,
navigationOptions: {
header: null
}
},
AppScreen:{
screen:AppNavigator // this is new , im adding stacknavigaoter to your drawer.
}
},
{
initialRouteName: 'Home',
}
);
export default createAppContainer(DrawerNavigator);
Hope that helps, otherwise feel free for doubts.
Mention your drawer navigator inside the stacknavigator just like below,
const myDrawerNavigator = createDrawerNavigator(
{
Home: { screen: YOUR_HOME },
},
{
contentComponent: SideMenu,
drawerWidth: Dimensions.get('window').width * 0.75
}
)
const RootStack = createStackNavigator({
SplashScreen: {
screen: SplashScreen,
navigationOptions: {
header: null,
},
},
SomeName: {
screen: myDrawerNavigator ,
navigationOptions: {
header: null,
},
},
})
Modify the above code as per your screen name and it will works fine...
I hope this helps thanks... :)

How to use hook with SwitchNavigator

I'm trying to use https://github.com/expo/react-native-action-sheet with switch navigator.
I'm not sure how to do the basic setup as the example in the readme is different than my App.js. I'm using react 16.8 so I should be able to use hooks.
My App.js
import { useActionSheet } from '#expo/react-native-action-sheet'
const AuthStack = createStackNavigator(
{ Signup: SignupScreen, Login: LoginScreen }
);
const navigator = createBottomTabNavigator(
{
Feed: {
screen: FeedScreen,
navigationOptions: {
tabBarIcon: tabBarIcon('home'),
},
},
Profile: {
screen: ProfileScreen,
navigationOptions: {
tabBarIcon: tabBarIcon('home'),
},
},
},
);
const stackNavigator = createStackNavigator(
{
Main: {
screen: navigator,
// Set the title for our app when the tab bar screen is present
navigationOptions: { title: 'Test' },
},
// This screen will not have a tab bar
NewPost: NewPostScreen,
},
{
cardStyle: { backgroundColor: 'white' },
},
);
export default createAppContainer(
createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: stackNavigator,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
);
const { showActionSheetWithOptions } = useActionSheet();
);
Update, I'm getting this error when calling the showActionSheetWithOptions inside my component:
Hooks can only be called inside the body of a function component. invalid hook call
This is my code:
import React, { Component } from 'react';
import { useActionSheet } from '#expo/react-native-action-sheet'
export default class NewPostScreen extends Component {
_onOpenActionSheet = () => {
const options = ['Delete', 'Save', 'Cancel'];
const destructiveButtonIndex = 0;
const cancelButtonIndex = 2;
const { showActionSheetWithOptions } = useActionSheet();
showActionSheetWithOptions(
{
options,
cancelButtonIndex,
destructiveButtonIndex,
},
buttonIndex => {
console.log(buttonIndex);
},
);
};
render () {
return (
<View>
<Button title="Test" onPress={this._onOpenActionSheet} />
</View>
)
}
}
update 2
I also tried using a functional component, but the actionsheet does not open (console does print "pressed")
// ActionSheet.js
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
import { useActionSheet } from '#expo/react-native-action-sheet'
export default function ActionSheet () {
const { showActionSheetWithOptions } = useActionSheet();
const _onOpenActionSheet = () => {
console.log("pressed");
const options = ['Delete', 'Save', 'Cancel'];
const destructiveButtonIndex = 0;
const cancelButtonIndex = 2;
showActionSheetWithOptions(
{
options,
cancelButtonIndex,
destructiveButtonIndex,
},
(buttonIndex) => {
console.log(buttonIndex);
},
);
};
return (
<TouchableOpacity onPress={_onOpenActionSheet} style={{height: 100,}}>
<Text>Click here</Text>
</TouchableOpacity>
);
};
Problem
As you can see here. You are not connecting your application root component.
Solution
import connectActionSheet from #expo/react-native-action-sheet and connect your application root component to the action sheet.
Simply modify your App.js to reflect the following:
// ... Other imports
import { connectActionSheet } from '#expo/react-native-action-sheet'
const AuthStack = createStackNavigator({
Signup: SignupScreen,
Login: LoginScreen
});
const navigator = createBottomTabNavigator({
Feed: {
screen: FeedScreen,
navigationOptions: {
tabBarIcon: tabBarIcon('home'),
},
},
Profile: {
screen: ProfileScreen,
navigationOptions: {
tabBarIcon: tabBarIcon('home'),
},
},
});
const stackNavigator = createStackNavigator({
Main: {
screen: navigator,
// Set the title for our app when the tab bar screen is present
navigationOptions: { title: 'Test' },
},
// This screen will not have a tab bar
NewPost: NewPostScreen,
}, {
cardStyle: { backgroundColor: 'white' },
});
const appContianer = createAppContainer(
createSwitchNavigator({
AuthLoading: AuthLoadingScreen,
App: stackNavigator,
Auth: AuthStack,
}, {
initialRouteName: 'AuthLoading',
})
);
const ConnectApp = connectActionSheet(appContianer);
export default ConnectApp;
Now on any of your application screens (i.e. Feed, Profile, Main, etc.) you can access the action sheet as follows:
If Stateless Component
// ... Other imports
import { useActionSheet } from '#expo/react-native-action-sheet'
export default function Profile () {
const { showActionSheetWithOptions } = useActionSheet();
/* ... */
}
If Statefull Component
// ... Other imports
import React from 'react'
import { useActionSheet } from '#expo/react-native-action-sheet'
export default Profile extends React.Component {
const { showActionSheetWithOptions } = useActionSheet();
/* ... */
}
Note: You can also access the action sheet as stated below from the docs
App component can access the actionSheet method as this.props.showActionSheetWithOptions

Pass parameters between drawer stacks react-navigation

My router setup is as below
import { createAppContainer, createDrawerNavigator, createStackNavigator, createSwitchNavigator } from "react-navigation";
import Home from "./components/Home";
import Search from "./components/Search";
import Map from "./components/Map";
import Login from "./components/Login";
import ForgotPassword from "./components/ForgotPassword";
import SideMenu from "./SideMenu";
const DashboardStack = createStackNavigator(
{
Home: { screen: Home },
Search : {screen : Search}
}
);
const MapStack = createStackNavigator(
{
Map: { screen: Map },
}
);
const AuthStack = createStackNavigator(
{
Login: { screen: Login },
ForgotPassword: { screen: ForgotPassword },
}
);
export const DrawerStack = createDrawerNavigator(
{
Dashboard: { screen: DashboardStack },
Map: { screen: MapStack },
},
{
contentComponent: SideMenu,
drawerWidth: 250
}
);
export const AppNavigator = createStackNavigator(
{
Drawer: { screen: DrawerStack },
Auth: { screen: AuthStack },
},
{
// initialRouteName: "Drawer",
headerMode: 'none',
mode: 'modal',
}
);
export default createAppContainer(DrawerStack);
Everything working fine, just a small issue. When I navigate to search screen from home and then switch to the Map screen with parameters, those parameters are not reaching to the Map screen.
My current setup is at codepan
Your problem is that your MapStack and your Map screen both have the same name, 'Map'.
Just replace the MapStack route to something else like 'MapStack' and you'll get the params.
See here: https://snack.expo.io/SyTFUPZUB
export const DrawerStack = createDrawerNavigator(
{
Dashboard: { screen: DashboardStack },
MapStack: { screen: MapStack },
},
{
contentComponent: SideMenu,
drawerWidth: 250
}
);
#sfratini is right
The issue is indeed "Map" key being present in two places.
So navigation.navigate("Map") will navigate to MapStack.
Navigating to stack means going to current screen of that stack which defaults to initialRouteName or first screen in the stack.
To verify this, add another screen as first screen in MapStack and check the behaviour.
So, solution to your issue is to rename "Map" key to something else, as suggested by #sfratini.
It works fine by just adding map screen to dashboard stack
const DashboardStack = createStackNavigator(
{
Home: { screen: Home },
Search : {screen : Search},
Map: { screen: Map }
}
);
then use
this.props.navigation.getParam('name', 'name is coming')
to get the name params value
here is the code
https://snack.expo.io/HyEFZeyLB
you can reach the parameters in your Map screen like following:
update this :
render() {
return (
<SafeAreaView style={styles.container}>
<Text>Map</Text>
</SafeAreaView>
)
}
to this :
render() {
return (
<SafeAreaView style={styles.container}>
<Text>{this.props.navigation.state.params.name}</Text>
</SafeAreaView>
)
}
and you have to put your Map screen in with home and search Stack like following:
import { createAppContainer, createDrawerNavigator, createStackNavigator,
createSwitchNavigator } from "react-navigation";
import Home from "./components/Home";
import Search from "./components/Search";
import Map from "./components/Map";
import Login from "./components/Login";
import ForgotPassword from "./components/ForgotPassword";
import SideMenu from "./SideMenu";
const DashboardStack = createStackNavigator(
{
Home: { screen: Home },
Search : {screen : Search},
Map: { screen: Map },
}
);
const AuthStack = createStackNavigator(
{
Login: { screen: Login },
ForgotPassword: { screen: ForgotPassword },
}
);
export const DrawerStack = createDrawerNavigator(
{
Dashboard: { screen: DashboardStack },
},
{
contentComponent: SideMenu,
drawerWidth: 250
}
);
export const AppNavigator = createStackNavigator(
{
Drawer: { screen: DrawerStack },
Auth: { screen: AuthStack },
} ,
{
// initialRouteName: "Drawer",
headerMode: 'none',
//mode: 'modal',
}
);
export default createAppContainer(DrawerStack);
the result from your snak :
hope this will help.

Using Tab and Stack Navigator Together

I am building an App on React-Native for which I am using React-Navigation
Now, Inside that i am using Stack-Navigation and TabNavigator (updated it DrawerNavigator)
import {
createStackNavigator,
TabNavigator,
DrawerNavigator
} from 'react-navigation';
import CoinCapCharts from "./src/container/CoinCapCharts.js"
import CoinCap from './src/container/CoinCap.js';
//THis is being Exported to App.js
export const Tab = TabNavigator({
TabA: {
screen: CoinCap
},
TabB: {
screen: CoinCap
}
}, {
order: ['TabA', 'TabB'],
animationEnabled: true,
})
export const MyScreen = createStackNavigator({
Home: {
screen: CoinCap
},
CoinCapCharts: {
screen: CoinCapCharts
}
},{
initialRouteName: 'Home',
headerMode: 'none'
});
export const Drawer = DrawerNavigator({
Tabs: { screen: Tab },
Stack: { screen: MyScreen },
})
I am importing this in my App.js where I am doing something like this
import React from 'react';
import {
Drawer
}from './Screen.js';
import {
View
} from 'react-native';
export default class App extends React.Component {
render() {
return (
<View>
<Drawer/>
<Tab/>
</View>
);
}
}
Now, This is indeed showing Tab the first time I run my app but after I navigate to different screen and return back, It doesn't appear to be showing that Tab again
[Question:] What could I be doing wrong and How can I fix it?
Try to define one within the other.
Something like:
const Tab = TabNavigator({
TabA: {
screen: Home
},
TabB: {
screen: Home
}
}, {
order: ['TabA', 'TabB'],
animationEnabled: true,
})
export const MyStack = createStackNavigator({
Home: {
screen: Home
},
CoinCapCharts: {
screen: CoinCapCharts
},
Tab: {
screen: Tab
},
},{
initialRouteName: 'Home',
headerMode: 'none'
});
Now, render MyStack (not sure that Screen is the best name :)
export default class App extends React.Component {
render() {
return (
<View>
<MyStack />
</View>
);
}
}