I have this issue whenever I toggle the drawer on my screen. I want to login and then go to Home page where there will be a drawer. But I don't know where the issue is.
PS: I have Expo managed project and I already installed react-native-gesture-handler and react-native-reanimated.
This is the code for navigating :
const Stack = createNativeStackNavigator();
const Drawer = createDrawerNavigator();
const DrawerComponent = () => {
return (
<Drawer.Navigator>
<Drawer.Screen name="Dashboard" component={Test} />
<Drawer.Screen name="Reset" component={Reset} />
</Drawer.Navigator>
);
};
const Navigation = () => {
return (
<Stack.Navigator>
<Stack.Screen name="StartUp" component={StartUp} />
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Register" component={Register} />
<Stack.Screen name="Reset" component={Reset} />
<Stack.Screen name="DrawerComponent" component={DrawerComponent} options={{title: "drawer"}}/>
</Stack.Navigator>
);
};
export default Navigation;
Related
I was trying to use TabNavigator in expo, but I have a problem, I have created a component where I have all the routes in a Tab, and in the other component I am only importing it.
in this component I have all the routes of my app:
const AppRouter = () => {
const Stack = createNativeStackNavigator();
const { user } = useContext(AuthContext);
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
>
{!user ? (
<>
<Stack.Screen name="login" component={Login} />
<Stack.Screen name="register" component={Register} />
</>
) : (
<>
<BottomTap />
</>
)}
</Stack.Navigator>
);
};
and in this component I am creating the Tabs with their routes:
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import Home from "../../screens/Home";
const Tab = createBottomTabNavigator();
const BottomTap = () => {
return (
<Tab.Navigator>
<Tab.Screen name="home" component={Home} />
</Tab.Navigator>
);
};
export default BottomTap;
Like the error says, navigators can only contain other navigators - not even custom components that contain only navigators. You can solve this by putting your tab navigator component inside a screen.
Instead of
<BottomTap />
Use
<Stack.Screen name="bottomTap" component={BottomTap} />
You can read more about this in the "Nesting Navigators" section of the React Navigation docs: https://reactnavigation.org/docs/nesting-navigators/
You are adding a React component inside of a navigator instead of 'Screen', 'Group' or 'React.Fragment'. The correct way to add a navigator inside another is:
...
{!user ? (
<>
<Stack.Screen name="login" component={Login} />
<Stack.Screen name="register" component={Register} />
</>
) : (
<>
<Stack.Screen name="bottomTap" component={BottomTap} />
</>
)}
...
I'm trying to use reactnavigation.org library and I have some issue with that. I have two types of navigation screens. Two screens are a registration and authorization. And others are regular app screens. Problem is that I can't render parent component App.js or other functionality to reload app from child component and thus change my screens block. Navigation between screens Run, History, Profile, OtherRunners works fine. Navigation between screens Main and Enter works fine. But if I need navigate from Run to Main, or from Enter to Run there is a problem.
App.js
const App = () => {
const Stack = createStackNavigator()
const Drawer = createDrawerNavigator()
const [loggedIn, setLoggedIn] = useState(false)
async function getUserEmail(){
if(await AsyncStorage.getItem('#email')){
setLoggedIn(true)
}else{
setLoggedIn(false)
}
}
getUserEmail()
function MenuDraw(){
return(
<Drawer.Navigator
drawerContentOptions={}
drawerType={}
drawerStyle={{}}
>
<Drawer.Screen
name="Run"
component={Run}
options={}
/>
<Drawer.Screen
name="History"
component={History}
options={}
/>
<Drawer.Screen
name="Profile"
component={Profile}
options={}
/>
<Drawer.Screen
name="OtherRunners"
component={OtherRunners}
options={}
/>
<Drawer.Screen
name="LogOut"
component={Run}
initialParams={{action: 'logout'}}
options={}
/>
</Drawer.Navigator>
)
}
function MyDrawer(){
if(loggedIn){
return(
<Stack.Navigator
screenOptions={{headerShown: false}}
initialRouteName={"MenuDraw"}
>
<Stack.Screen name="MenuDraw" component={MenuDraw}/>
<Stack.Screen name="Details" component={Details}/>
</Stack.Navigator>
)
}else{
return (
<Stack.Navigator
screenOptions={{headerShown: false}}
initialRouteName={"Main"}
>
<Stack.Screen name="MenuDraw" component={MenuDraw} />
<Stack.Screen name="Details" component={Details} />
<Stack.Screen name="Main" component={Main} />
<Stack.Screen name="Enter" component={Enter} />
</Stack.Navigator>
)
}
}
return(
<NavigationContainer>
<MyDrawer/>
</NavigationContainer>
)
}
export default App;
I tried using reload app tools, but those wasn't help me. They are wasn't working. In this section of code which is below. On the Run screen.
Run.js
const Run = ({navigation,route}) => {
const clearStorage = async () => {
await AsyncStorage.clear()
}
if(route.params){
if(route.params.action === 'logout'){
clearStorage()
navigation.navigate("Main", {})
}
}
}
export default Run;
I'm trying to logout by cleaning the storage and navigate to Main screen. But it's not working on release mode. I've tried this, which is below.
App.js
function MyDrawer(){
if(loggedIn){
return(
<Stack.Navigator
screenOptions={{headerShown: false}}
initialRouteName={"MenuDraw"}
>
<Stack.Screen name="MenuDraw" component={MenuDraw}/>
<Stack.Screen name="Details" component={Details}/>
++++ <Stack.Screen name="Main" component={Main} />
++++ <Stack.Screen name="Enter" component={Enter} />
</Stack.Navigator>
)
}else{
return (
<Stack.Navigator
screenOptions={{headerShown: false}}
initialRouteName={"Main"}
>
<Stack.Screen name="MenuDraw" component={MenuDraw} />
<Stack.Screen name="Details" component={Details} />
<Stack.Screen name="Main" component={Main} />
<Stack.Screen name="Enter" component={Enter} />
</Stack.Navigator>
)
}
}
Not working either way. How can I fix it? Can I render App.js component from child screens? Or perhaps I should create two screen blocks line
<Stack.Screen name="MenuDraw" component={MenuDraw}/>
<Stack.Screen name="MenuRegister" component={MenuRegister}/>
and put all my screens by belongings to match section?
I need to logout from this section:
App.js
some code
<Drawer.Screen
name="LogOut"
component={Run}
initialParams={{action: 'logout'}}
options={}
/>
</Drawer.Navigator>
some code
Did you try using useEffect hook, to get on the road? :-)
useEffect(() => {
const getUserEmail = async () => {
if(await AsyncStorage.getItem('#email')){
setLoggedIn(true)
}else{
setLoggedIn(false)
}
};
getUserEmail();
}, []);
This is my structure:
const RootStack = () => (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeTabs} />
<Stack.Screen name="AddNote" component={AddNoteScreen} />
</Stack.Navigator>
);
const HomeTabs = () => (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStack}/>
<Tab.Screen name="Customers" component={CustomersStack}/>
</Tab.Navigator>
);
const HomeStack = () => (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen}/>
<Stack.Screen name="Tickets" component={TicketsStack}/>
</Stack.Navigator>
);
const CustomerStack = () => (
<Stack.Navigator>
<Stack.Screen name="Customer" component={CustomerScreen}/>
<Stack.Screen name="Tickets"
initialParams={{ parentRouteConfig: true }}
component={TicketsStack}
/>
</Stack.Navigator>
);
const TicketStack = (props) => {
const { route } = props;
const { params } = route;
return (
<Stack.Navigator>
<Stack.Screen
name={params?.parentRouteConfig ? 'CustomerTickets' : 'Tickets'}
component={params?.parentRouteConfig ? CustomerTicketsScreen : TicketsScren}
/>
<Stack.Screen name="TicketDetail" component={TicketDetailScreen} />
</Stack.Navigator>
);
};
The problem is: In ticket stack I need to decide which screen should I render. FYI: to navigate from drawer or any other higher navigator,
I needed to give different name to Screen. Current implementation solves the problem that I have. But it smells, I know that
there is a better solution for this but I can't find it. What is the best practice to achieve this? Instead of initialParams can I use different technique?
Based on react-navigation documentation, I'm doing the following for all my "conditional screen".
<Stack.Navigator>
{params?.yourConditionVariable ? (
<Stack.Screen
name="CustomerTickets"
component={CustomerTicketsScreen}
/>
) : (
<Stack.Screen name="Tickets" component={TicketsScreen} />
)}
</Stack.Navigator>
It works pretty well, and it's the biggest feature of RN v5 on my side. I really love this flexibility!
Need to Show Tabs For Home Module after Signup Module
using React-navigation
Working Code with Only Stack Screens
const Stack = createStackNavigator();
const Bottom = createBottomTabNavigator();
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome" headerMode='none' >
<Stack.Screen name="Welcome" component={WelcomeScreen}
options={{
title: '',
headerBackTitleVisible: false,
headerBackTitle: '',
headerShown: true
}}
/>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
<Stack.Screen name="ResetPassword" component={ResetPasswordScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Need to show Tab from SigninScreen Button
Tab 1: Dashboard:
Tab 2: Profile
Tried Code:
<Bottom.Navigator initialRouteName="Dashboard" >
<Bottom.Screen name="Dashboard" component={TabDashboard} />
<Bottom.Screen name="Profile" component={TabProfile} />
</Bottom.Navigator>
Now I need to combine these two block of codes so I can navigate to Tabs
Tab screen will have further navigations
The idea would be to wrap the tabs screen inside component and add it to the stack conditionally.
const HomeScreen = () =>{
return (
<Bottom.Navigator initialRouteName="Dashboard" >
<Bottom.Screen name="Dashboard" component={TabDashboard} />
<Bottom.Screen name="Profile" component={TabProfile} />
</Bottom.Navigator>
);
}
Your stack should change as below
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome" headerMode='none' >
{
this.state.isSignedIn ? (
<>
<Stack.Screen name="Welcome" component={WelcomeScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
<Stack.Screen name="ResetPassword" component={ResetPasswordScreen} />
</>
) : (
<>
<Stack.Screen name="ResetPassword" component={HomeScreen} />
</>
)
}
</Stack.Navigator>
</NavigationContainer>
);
}
IsSignedIn can be the state variable or a variable that you store the logged in status
You can refer the authentication flows
https://reactnavigation.org/docs/auth-flow
I have a Navigation Drawer which should appear in all my screen(Except for the Splash screen).
I've got it that way:
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const StackNavigator = () => {
return (
<Stack.Navigator>
<Stack.Screen name="EstateDetails" component={Screens.EstateDetails} />
<Stack.Screen name="Tour" component={Screens.Tour} />
<Stack.Screen name="Comparison" component={Screens.Comparison} />
<Stack.Screen name="Blog" component={Screens.Blog} />
<Stack.Screen name="Auth" component={Screens.Auth} />
</Stack.Navigator>
);
};
const DrawerNavigator = () => {
return (
<Drawer.Navigator drawerContent={props => CustomDrawerContent(props)}>
<Drawer.Screen name="HomeScreen" component={Screens.Home} />
<Drawer.Screen name="stack" component={StackNavigator} />
<Drawer.Screen name="RegisterEstate" component={Screens.RegisterEstate} />
<Drawer.Screen name="Filter" component={Screens.Filter} />
<Drawer.Screen name="Conditions" component={Screens.Conditions} />
<Drawer.Screen name="Judicial" component={Screens.Judicial} />
<Drawer.Screen name="ContactUs" component={Screens.ContactUs} />
<Drawer.Screen name="ReportBugs" component={Screens.ReportBugs} />
</Drawer.Navigator>
)
};
export const AppNavigator = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Splash">
<Stack.Screen name="Splash" component={Screens.Splash}/>
<Stack.Screen name="Home" component={DrawerNavigator}/>
</Stack.Navigator>
</NavigationContainer>
);
};
In this case, all the okay only stack screens act as drawer screen.
(The screen only loads once and shows the initial load next time, like blog screens).
I need to have the cursor on all pages except splash and to stack some of my pages (like dynamic pages that don't have the same content)
If you want to display same drawer in all other screens just pass {DrawerNavigator} to all other screens where you want to show the Drawer.So in your example if you want to show Drawer in Tour and Blog screen just add
<Stack.Screen name="Blog " component={DrawerNavigator} />
<Stack.Screen name="Tour" component={DrawerNavigator} />
Now you can access in Blog and Tour screen.
If you want to show a different Drawer in other screens then Create a new function.