Nesting stack navigation inside a drawer navigation - react-native

I am trying to nest a stack navigation inside a drawer navigation on snack expo. I asked this question before and was told to do it all over again. I did and I still get different errors. I would really appreciated if someone could explain what am I doing wrong? I can also post the link to my project if this helps https://snack.expo.io/#andreeam/it-in-the-valley
Thank you
Errors below:
Device: (3:9741) (0,l.useLinkBuilder) is not a function. (In '(0,l.useLinkBuilder)()', '(0,l.useLinkBuilder)' is undefined)
And I also get
Device: (104:51757) r.render is not a function. (In 'r.render()', 'r.render' is undefined)
Cannot assign to read only property 'exports' of object '#<Object>'
Evaluating module://react-native-screens.js
Evaluating module://#react-navigation/drawer.js
Evaluating module://App.js.js
Loading module://App.js
Here is my app.js
import * as React from 'react';
import { createStackNavigator } from '#react-navigation/stack';
import { NavigationContainer } from '#react-navigation/native';
import SignIn from './components/SignIn';
import ForgotPassword from './components/ForgotPassword';
import Dashboard from './components/Dashboard';
import Advertisers from './components/Advertisers';
import Adverts from './components/Adverts';
import Stats from './components/Stats';
import Plans from './components/Plans';
import ManageAdverts from './components/manageadvert';
const Stack = createStackNavigator();
class MyStack extends React.Component {
render() {
return (
<Stack.Navigator
initialRouteName="SignIn"
screenOptions={{
headerTitleAlign: 'center',
headerStyle: { backgroundColor: '#2d3436'},
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold'}
}}>
<Stack.Screen
name="Reset your password"
component={ForgotPassword}
options={
{title: 'Reset your password'},
{headerLeft: null}
}
/>
<Stack.Screen
name="SignIn"
component={SignIn}
options = {
{headerShown: false,
title: 'SignOut'}
}
/>
<Stack.Screen
name="Dashboard"
component={Dashboard}
/>
<Stack.Screen
name="Advertisers"
component={Advertisers}
options={
{title: 'Advertisers'}
}
/>
<Stack.Screen
name="Adverts"
component={Adverts}
options={
{title: 'Adverts'}
}
/>
<Stack.Screen
name="Stats"
component={Stats}
options={
{title: 'Stats'}
}
/>
<Stack.Screen
name="Plans"
component={Plans}
options={
{title: 'Plans'}
}
/>
<Stack.Screen
name="Manage Adverts"
component={ManageAdverts}
options={
{title: 'Manage Adverts'}
}
/>
</Stack.Navigator>
);
}}
export default class App extends React.Component {
render() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}
}

I got this error when I upgraded expo to version 37. I was able to resolve this issue by updating the relevant reactmodules to the latest version.

Related

In React Native, I am getting this error "Could not find root view for a given ancestor with tag <no.>"

I was implementing the bottom-tab navigation feature and I am getting this error
Could not find root view for a given ancestor with tag number
Attaching error message with piece of code which causing this error.
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import {
Home,
Profile,
Explore,
} from '../Screens';
import navigationStrings from '../constants/navigationStrings';
const Stack = createStackNavigator();
function Routes() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName={navigationStrings.HOME} screenOptions={{ headerShown: false }}>
<Stack.Screen options={{ title: 'Book Your Book' }} name={navigationStrings.HOME} component={Home} />
<Stack.Screen name={navigationStrings.PROFILE} component={Profile} />
<Stack.Screen name={navigationStrings.EXPLORE} component={Explore} />
</Stack.Navigator>
</NavigationContainer >
)
}
export default Routes;

Combining a stack navigator with a drawer navigator in react native

So I'm new to react native and react navigation.
I'm building an app that will have 7 main screens:
HomeScreen, ProfileScreen, CocktailDetailScreen and PublishRecipeScreen (which I want to be able to access through a drawer navigator).
LandingScreen, LoginScreen and RegisterScreen (which I don't want to show in the drawer navigator. I just want to show the LandingScreen when the user isn't logged in, and either of the other if the user want's to log in or register).
I've been able to put up a stack navigator that works fine, but I don't understand how to combine this with the drawer navigator I want. I've tried different approaches but I get errors like:
The action 'OPEN_DRAWER' was not handled by any navigator.
Is your screen inside a Drawer navigator?
or
Uncaught Error: Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, pass 'independent={true}' explicitly. Note that this will make the child navigators disconnected from the parent and you won't be able to navigate between them.
This is my code so far.
App.tsx
import { SafeAreaProvider } from 'react-native-safe-area-context'
import useCachedResources from './hooks/useCachedResources'
import Navigation from './navigation'
export default function App() {
const isLoadingComplete = useCachedResources()
if (!isLoadingComplete) {
return null
} else {
return (
<SafeAreaProvider>
<Navigation />
</SafeAreaProvider>
)
}
}
(navigation) index.tsx
import { NavigationContainer } from '#react-navigation/native'
import { createNativeStackNavigator } from '#react-navigation/native-stack'
import * as React from 'react'
import LandingScreen from '../screens/LandingScreen'
import LoginScreen from '../screens/LoginScreen'
import RegisterScreen from '../screens/RegisterScreen'
import HomeScreen from '../screens/HomeScreen'
import ProfileScreen from '../screens/ProfileScreen'
import CocktailDetailScreen from '../screens/CocktailDetailScreen'
import PublishRecipeScreen from '../screens/PublishRecipeScreen'
import Header from '../components/Header'
import DrawerNavigator from '../components/DrawerNavigator'
import { RootStackParamList } from '../types'
export default function Navigation() {
const Stack = createNativeStackNavigator<RootStackParamList>()
return (
<NavigationContainer>
<Stack.Navigator >
<Stack.Screen name='LandingScreen' component={LandingScreen} options={{headerShown: false}} />
<Stack.Screen name='LoginScreen' component={LoginScreen} options={{headerShown: false}} />
<Stack.Screen name='RegisterScreen' component={RegisterScreen} options={{headerShown: false}} />
<Stack.Screen name='HomeScreen' component={HomeScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='ProfileScreen' component={ProfileScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='PublishRecipeScreen' component={PublishRecipeScreen} options={{ header: () => <Header/> }} />
</Stack.Navigator>
</NavigationContainer>
)
}
header.tsx
import React from 'react'
import { useNavigation } from '#react-navigation/native'
import { useDrawerStatus } from '#react-navigation/drawer'
import { DrawerActions } from '#react-navigation/native'
import { StyleSheet, Text, View } from 'react-native'
import { AntDesign } from '#expo/vector-icons'
const Header = () => {
const navigation = useNavigation()
return (
<View style={styles.container}>
<Text style={styles.title} onPress={() => navigation.navigate('RegisterScreen')}>Mixr</Text>
<View style={styles.iconContainer} >
<AntDesign name='user' style={styles.icon} size={30} color='white' onPress={() => navigation.dispatch(DrawerActions.openDrawer())} />
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#E51C27',
alignSelf: 'stretch'
},
title: {
fontSize: 40,
fontWeight: 'bold',
marginTop: 6,
marginBottom: 6,
marginLeft: 10
},
iconContainer: {
backgroundColor: 'black',
borderBottomLeftRadius: 50,
borderBottomRightRadius: 50,
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
marginRight: 10
},
icon: {
padding: 5
}
})
export default Header
DrawerNavigator.tsx
import React from 'react'
import { createDrawerNavigator, useDrawerStatus } from '#react-navigation/drawer'
import { NavigationContainer } from '#react-navigation/native'
import HomeScreen from '../screens/HomeScreen'
import ProfileScreen from '../screens/ProfileScreen'
import CocktailDetailScreen from '../screens/CocktailDetailScreen'
import PublishRecipeScreen from '../screens/PublishRecipeScreen'
const DrawerNavigator = () => {
const Drawer = createDrawerNavigator()
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name='HomeScreen' component={HomeScreen} />
<Drawer.Screen name='ProfileScreen' component={ProfileScreen} />
<Drawer.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} />
<Drawer.Screen name='PublishRecipeScreen' component={PublishRecipeScreen} />
</Drawer.Navigator>
</NavigationContainer>
)
}
export default DrawerNavigator
I want to show a header in all of this pages (HomeScreen, ProfileScreen, CocktailDetailScreen and PublishRecipeScreen) and from that header be able to open/close the drawer. I don't quite understand how to link the stack navigator with the drawer.
From a more theoretical point of view, I don't really understand the difference between the stack navigator, the drawer, and other options like tab or bottom navigators.
I mean, besides that the drawer navigator shows in a drawer and the bottom one shows at the bottom. Is there a conceptual difference between them?
Full code can be found here: https://github.com/coccagerman/mixr
I think I figured it out.
What I did is nest the drawer navigator within the stack navigator.
To do so, I passed the Drawer navigator as the component of each of the screens I wanted it to be in.
Like so:
(navigation) index.tsx
import { NavigationContainer } from '#react-navigation/native'
import { createNativeStackNavigator } from '#react-navigation/native-stack'
import * as React from 'react'
import LandingScreen from '../screens/LandingScreen'
import LoginScreen from '../screens/LoginScreen'
import RegisterScreen from '../screens/RegisterScreen'
import Header from '../components/Header'
import DrawerNavigator from '../components/DrawerNavigator'
import { RootStackParamList } from '../types'
export default function Navigation() {
const Stack = createNativeStackNavigator<RootStackParamList>()
return (
<NavigationContainer>
<Stack.Navigator >
<Stack.Screen name='LandingScreen' component={LandingScreen} options={{headerShown: false}} />
<Stack.Screen name='LoginScreen' component={LoginScreen} options={{headerShown: false}} />
<Stack.Screen name='RegisterScreen' component={RegisterScreen} options={{headerShown: false}} />
<Stack.Screen name='HomeScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
<Stack.Screen name='ProfileScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
<Stack.Screen name='CocktailDetailScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
<Stack.Screen name='PublishRecipeScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
</Stack.Navigator>
</NavigationContainer>
)
}
And in the drawer navigator I assign the corresponding screen component to each screen:
DrawerNavigator.tsx
import React from 'react'
import { createDrawerNavigator } from '#react-navigation/drawer'
import HomeScreen from '../screens/HomeScreen'
import ProfileScreen from '../screens/ProfileScreen'
import CocktailDetailScreen from '../screens/CocktailDetailScreen'
import PublishRecipeScreen from '../screens/PublishRecipeScreen'
const DrawerNavigator = () => {
const Drawer = createDrawerNavigator()
return (
<Drawer.Navigator>
<Drawer.Screen name='Home' component={HomeScreen} options={{headerShown: false}} />
<Drawer.Screen name='Profile' component={ProfileScreen} options={{headerShown: false}} />
<Drawer.Screen name='CocktailDetail' component={CocktailDetailScreen} options={{headerShown: false}} />
<Drawer.Screen name='PublishRecipe' component={PublishRecipeScreen} options={{headerShown: false}} />
</Drawer.Navigator>
)
}
export default DrawerNavigator
I still find this a bit confusing though, and I guess there's probably a simpler way to write this.
Useful resources I've found on this topic:
https://reactnavigation.org/docs/nesting-navigators/
https://blog.waldo.io/combining-navigators-in-react-navigation/

Trying to make a Home Screen in React-Native

I am new to React-Native and I am trying to make a Home Page in my app and at the same time declare some components.
Here is the code I tried to implement
import React from "react";
import {createAppContainer} from '#react-navigation/native'
import {createStackNavigator} from '#react-navigation/stack'
import Buttons from "./Buttons.js"
import PlaylistScreen from "./react/screens/PlaylistScreen.js"
// const navigator = createStackNavigator (
// {
// ButtonsScreen: Buttons,
// Playlist: {
// screen: Playlist
// }
// },
// {
// initialRouteName:'ButtonsScreen',
// defaultNavigationOptions: {
// title:"App"
// }
// }
// );
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator
initialRouteName="Buttons"
headerMode="screen"
screenOptions={{
headerTintColor: 'white',
headerStyle: { backgroundColor: 'tomato' },
}}
>
<Stack.Screen
name="ButtonsScreen"
component={Buttons}
options={{
title: 'Awesome app',
}}
/>
<Stack.Screen
name="Playlist"
component={ {screen: PlaylistScreen}}
options={{
title: 'My profile',
}}
/>
</Stack.Navigator>
);
}
export default createAppContainer(Stack);
However, I have encounterd problems, giving me those errors:
enter image description here
Please help me, I would be very grateful. :)
https://reactnavigation.org/docs/stack-navigator
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Notifications" component={Notifications} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
);
}
I have reformatted your code by wrapping your stack navigator inside navigation container and exported MyStack component to be like this:
import {NavigationContainer} from '#react-navigation/native';
const Stack = createStackNavigator();
function MyStack() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Buttons"
headerMode="screen"
screenOptions={{
headerTintColor: 'white',
headerStyle: { backgroundColor: 'tomato' },
}}
>
<Stack.Screen
name="ButtonsScreen"
component={Buttons}
options={{
title: 'Awesome app',
}}
/>
<Stack.Screen
name="Playlist"
component={ {screen: PlaylistScreen}}
options={{
title: 'My profile',
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default MyStack;

Using drawer navigation and stack navigation at the same time

I am trying to nest a stack navigation inside a drawer navigation on snack expo. I asked this question before and was told to do it all over again. I did and still got errors. Initially I used a class, so I tried using a function instead . I would really appreciate if someone could explain what am I doing wrong? I can also post the link to my project if this helps https://snack.expo.io/#andreeam/it-in-the-valley
The error I get is
Device: (0:0) Cannot assign to read only property 'exports' of object '#<Object>'
Evaluating module://react-native-screens.js
Evaluating module://#react-navigation/drawer.js
Evaluating module://App.js.js
Loading module://App.js
Thank you
This is my code
import * as React from 'react';
import { createStackNavigator } from '#react-navigation/stack';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import SignIn from './components/SignIn';
import ForgotPassword from './components/ForgotPassword';
import Dashboard from './components/Dashboard';
import Advertisers from './components/advertisers';
import Adverts from './components/Adverts';
import Stats from './components/Stats';
import Plans from './components/Plans';
import About from './components/about';
import ManageAdvert from './components/ManageAdvert';
const Stack = createStackNavigator();
function Root () {
return (
<Stack.Navigator
initialRouteName="SignIn"
screenOptions={{
headerTitleAlign: 'center',
headerStyle: { backgroundColor: '#2d3436'},
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold'}
}}>
<Stack.Screen
name="Reset your password"
component={ForgotPassword}
options={
{title: 'Reset your password'},
{headerLeft: null}
}
/>
<Stack.Screen
name="SignIn"
component={SignIn}
options = {
{headerShown: false,
title: 'SignOut'}
}
/>
<Stack.Screen
name="Dashboard"
component={Dashboard}
/>
<Stack.Screen
name="Advertisers"
component={Advertisers}
options={
{title: 'Advertisers'}
}
/>
<Stack.Screen
name="Adverts"
component={Adverts}
options={
{title: 'Adverts'}
}
/>
<Stack.Screen
name="Stats"
component={Stats}
options={
{title: 'Stats'}
}
/>
<Stack.Screen
name="Plans"
component={Plans}
options={
{title: 'Plans'}
}
/>
<Stack.Screen
name="Manage Adverts"
component={ManageAdvert}
options={
{title: 'Manage Adverts'}
}
/>
</Stack.Navigator>
);
}
const Drawer = createDrawerNavigator();
export default function App () {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Root">
<Drawer.Screen name="Root" component={Root} />
<Drawer.Screen name="About" component={About} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Fixed that, see snack here => https://snack.expo.io/#mustafaskir/ee857b
just updated packages in package.json, should fix that
here's what packages i updated, and i have to republish in my acc
"react-native-paper": "^3.10.1",
"react-native-screens": "^2.4.0",
"#react-navigation/stack": "^5.3.7",
"react-native-reanimated": "^1.8.0",
"#react-navigation/drawer": "^5.7.5",
"#react-navigation/native": "^5.4.0",
"react-native-safe-area-context": "^0.7.3",
"#react-native-community/masked-view": "^0.1.7"

Setting up customizable Header in React Native

I wish to create Header for my Notes Storage App on React Native. I have Tried using stackNavigator till now but I am caught up on how to add menu icon which onPres will open the Drawer. I tried using HeaderLeft in stackDesignHead but it gives an error. Also using a FAB is not recommended.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import HomePage from './src/HomePage/HomePage';
import NotesFolder from './src/notes';
import CreateNewFolder from './src/CreateNewFolder';
import Icon from 'react-native-vector-icons/Ionicons';
import Constants from 'expo-constants';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
const stackDesignHead = {
title: "Notes Classifier",
headerTintColor:"white",
headerStyle:{
backgroundColor:"#fcba03"
},
headerTitleStyle: {
fontWeight: 'bold',
},
headerTitleAlign: 'center'
}
function LeftDrawer () {
return(
<Stack.Navigator>
<Stack.Screen
name="HomePage"
component={HomePage}
options={stackDesignHead}
/>
<Stack.Screen
name="NotesFolder"
component={NotesFolder}
options={{...stackDesignHead,title:"Notes"}}
/>
<Stack.Screen
name="CreateNewFolder"
component={CreateNewFolder}
options={{...stackDesignHead,title:"+ new Folder"}}
/>
</Stack.Navigator>
)
}
const menuDesignHead = {
title: "Notes Classifier",
headerTintColor:"white",
headerStyle:{
backgroundColor:"#fcba03"
},
headerTitleStyle: {
fontWeight: 'bold',
},
headerTitleAlign: 'center'
}
function App () {
return(
<View style={styles.container}>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen
name="Home"
component={LeftDrawer}
options={{menuDesignHead}}
/>
</Drawer.Navigator>
</View>
);
}
export default()=>{
return(
<NavigationContainer>
<App/>
</NavigationContainer>
)
}
I am new to react native and unaware of various ways to create header.
Provides a way to create your own custom headers in React-navigation documents.
Replacing the title with a custom component
Sometimes you need more control than just changing the text and styles of your title -- for example, you may want to render an image in place of the title, or make the title into a button. In these cases you can completely override the component used for the title and provide your own.
Example
function LogoTitle() {
return (
<Image
style={{ width: 50, height: 50 }}
source={require('#expo/snack-static/react-native-logo.png')}
/>
);
}
function StackScreen() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerTitle: props => <LogoTitle {...props} /> }}
/>
</Stack.Navigator>
);
}