How to Check the login state? - javascript

I have a navigator as below. I want to show the drawer when the user logged in. However, the isLogin will still be false after I login. As I am quit new to react native, is there any solution to this issue? Also, I want to know if there are any good sources for learning react native?
let isLogin = firebase.auth().currentUser ? true : false;
const HomeStack = () => {
return (
<Stack.Navigator
screenOptions={{
headerStyled: {
backgroundColor: primary,
},
headerLeftContainerStyle: {
paddingLeft: 20,
},
headerShown: false,
}}
initialRouteName="Home"
>
<Stack.Screen name="HomeScreen" component={Home} />
<Stack.Screen name="Login" component={Login} />
</Stack.Navigator>
);
};
console.log(isLogin);
const LoginStack = () => {
return (
<Stack.Navigator
screenOptions={{
headerStyled: {
backgroundColor: primary,
},
headerLeftContainerStyle: {
paddingLeft: 20,
},
headerShown: false,
}}
initialRouteName="Login"
>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Signup" component={Signup} />
<Stack.Screen name="Home" component={Home} />
</Stack.Navigator>
);
};
const RootStack = () => {
return (
<NavigationContainer>
{/* {isLogin ? (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={HomeStack} />
<Drawer.Screen name="Chat" component={Chat} />
</Drawer.Navigator>
) : (
<LoginStack />
)} */}
<LoginStack />
</NavigationContainer>
);
};
export default RootStack;

Because you initialize isLogin variable outside the component, you get value only one time. So you need to put declaring variable into the component.
const RootStack = () => {
let isLogin = firebase.auth().currentUser ? true : false;
return (
<NavigationContainer>
{/* {isLogin ? (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={HomeStack} />
<Drawer.Screen name="Chat" component={Chat} />
</Drawer.Navigator>
) : (
<LoginStack />
)} */}
<LoginStack />
</NavigationContainer>
);
};

Related

How can I add an onPress event listener to a drawer navigation item in react native react navigation?

I have a drawer navigation configured in the following way:
const CustomDrawerContent = () => { return ( <DrawerItem label="Log out2" onPress={() => logOut()} /> ) }
const loginStack = () => (
<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.Navigator>
)
return (
<NavigationContainer>
<Drawer.Navigator
screenOptions={{
drawerStyle: { backgroundColor: 'white' },
drawerPosition: 'right'
}}>
{!user ? (
<Drawer.Screen
name="PublicStack"
component={loginStack}
options={{headerShown: false}}
/> )
:
(<>
<Drawer.Screen name='Search cocktails' component={HomeScreen} options={{ header: () => <Header/> }} />
<Drawer.Screen name='Profile' component={ProfileScreen} options={{ header: () => <Header/> }} />
<Drawer.Screen name='Publish a recipe' component={PublishRecipeScreen} options={{ header: () => <Header/> }} />
<Drawer.Screen name='Favorites' component={FavoritesScreen} options={{ header: () => <Header/> }} />
<Drawer.Screen name='Published recipes' component={PublishedRecipesScreen} options={{ header: () => <Header/> }} />
<Drawer.Screen name='Log out' component={CustomDrawerContent} options={{ header: () => <Header/> }} />
<Drawer.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} options={{
header: () => <Header/>,
drawerLabel: () => null,
title: undefined
}} />
</>
)}
</Drawer.Navigator>
</NavigationContainer>
)
All screens work fine, but I want Log out to execute a logout function onPress. As I understand, I can't add this event listener directly on the screen component, so I followed this doc (https://reactnavigation.org/docs/drawer-navigator/#drawercontent) and tried a few different things:
I created the component CustomDrawerContent which is a DrawerItem.
If I pass CustomDrawerContent as the component to the Log out screen (as the code is right now), when I click on it I get redirected to a blank page that renders CustomDrawerContentcomponent, which isn't what I want.
If I pass CustomDrawerContent as drawerContent props to the drawer navigator, like the doc says (example below), all other screens dont render anymore, which is again not what I want.
<Drawer.Navigator drawerContent={(props) => <CustomDrawerContent />}>
{/* screens */}
</Drawer.Navigator>
If I put the drawer item together with the screens inside the navigator, the app throws the following error:
useNavigationBuilder.tsx:134 Uncaught Error: A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found 'DrawerItem'). To render this component in the navigator, pass it in the 'component' prop to 'Screen'.
So how can I add the item to the drawer without 'overwritting' the screens?
Or is there other way to put a simple logout button in the drawer?
Full code can be found here: https://github.com/coccagerman/mixr

Undefined is not an object (evaluating 'route.params.title')

I followed the React Navigation Doc to achieve a Dynamic header title change but It shows the error Undefined is not an object (evaluating 'route.params.title').
My tabs.js:
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<HomeStack.Screen
name="Profile"
component={Profile}
options={({ route }) => ({ title: route.params.title })}
/>
</HomeStack.Navigator>
);
}
The Home.js has the onpress like that:
<TouchableOpacity
onPress={() => {
navigation.navigate('Profile', {
title: 'Custom title',
});
}}
>
And Profile.js:
function Profile({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Hello</Text>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
Add a check/default value on your params, because route.params is not always valorized, but only when you navigate on that page.
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<HomeStack.Screen
name="Profile"
component={Profile}
options={({ route }) => ({ title: route.params?.title || "DEFAULT TITLE" })}
/>
</HomeStack.Navigator>
);
}

Is there a way to navigate between screens that is not defined in the NavigationContainer in ReactNavigation?

I'm trying to navigate to my Login screen, but I haven't defined my Login screen in my NavigationContainer. This is because I don't want the Login screen to be a tab in my navbar. This leads to my question: Is there a way to navigate to the Login screen, without having it as a tab in the navbar?
export default function App() {
return (
<NavigationContainer>
<SafeAreaView style={{flex: 1}}>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'home-outline'
: 'home-outline';
} else if (route.name === 'Profile') {
iconName = focused ? 'person-circle-outline' : 'person-circle-outline';
} else if (route.name === 'Calendar') {
iconName = focused ? 'calendar-clear' : 'calendar-clear';
} else if (route.name === 'Agenda') {
iconName = focused ? 'calendar-outline' : 'calendar-outline';
}
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: 'blue',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
<Tab.Screen name="Calendar" component={CalendarScreen} />
<Tab.Screen name="Agenda" component={AgendaScreen} />
<Tab.Screen name="New Event" component={NewEventScreen} />
</Tab.Navigator>
</SafeAreaView>
</NavigationContainer>
);
}
<Button
title="Do you have an account? Click here to log in"
onPress={() => this.props.navigation.navigate("Login")}
/>
This is an example of how it can be done:
private render() {
const Stack = createStackNavigator();
const landingScreen = this.props.isLoggedIn ? null : (
<Stack.Screen
name="LoginScreen"
component={LoginScreen}
/>
);
return (
<NavigationContainer>
<Stack.Navigator>
{landingScreen}
<Stack.Screen name="HomeScreen" component={this.renderTabNavigator}/>
</Stack.Navigator>
</NavigationContainer>
);
}
private renderTabNavigator = () => {
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={SearchScreen}/>
<Tab.Screen name="Favorites" component={FavoritesScreen}/>
<Tab.Screen name="Settings" component={SettingsScreen}/>
</Tab.Navigator>
);
}

tabnavigation hidden after login React native

I am using tabnavigator and stacknavigator, and after my connection I cannot be redirected to my home navigation unless I add Home to my stacknavigator, but tabnavigator disappears. I would like to know what I should do to be sent to my home navigation, so that my tabnavigator does not disappear.
const [user, setUser] = useState(false);
useEffect(()=> {
setTimeout(() => {
User()
console.log("Update")
}, 500);
},)
const User = async() => {
const value = await AsyncStorage.getItem('#user')
if (value === null) {
console.log('disconnecte')
}else {
setUser(true)
console.log("online")
navigation.navigate('Home')
}
}
return (
<NavigationContainer>
{user === false ? <Authnavigator/> : <Stacknavigator /> }
</NavigationContainer>
)
}
StackNavigator
export default function Stacknavigator() {
return (
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="TabNavigator" component={TabNavigator} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
)
}
Authnavigator
export default function Authnavigator() {
return (
<AuthStack.Navigator screenOptions={{
headerShown: false
}}>
<AuthStack.Screen name="Login" component={Login} />
</AuthStack.Navigator>
)
}
Update :
the login navigation to Home works but then to go to the Details view it does not work
export default function Stacknavigator() {
return (
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Tabnavigator" component={Tabnavigator} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
)
}
Tabnavigator
export default function Tabnavigator() {
return (
<Tab.Navigator
initialRouteName="Home"
activeColor="#f0edf6"
inactiveColor="#6D6D6D"
barStyle={{ backgroundColor: '#171717' }}
>
<Tab.Screen name="Home" component={Home} options= {{
tabBarIcon: ({ color }) => (
<FontAwesome name="home" size={20} color={(color)} />
)
}} />
<Tab.Screen name="Recherche" component={Search} options={{
tabBarIcon: ({color}) => (
<FontAwesome name="search" size={20} color={(color)} />
)
}} />
<Tab.Screen name="Favorie" component={Favorie} options={{
tabBarIcon: ({color}) => (
<FontAwesome name="star" size={20} color={(color)} />
)
}}/>
</Tab.Navigator>
)
}
const Tab = createMaterialBottomTabNavigator();
Authnavigator
export default function Authnavigator() {
return (
<AuthStack.Navigator screenOptions={{
headerShown: false
}}>
<AuthStack.Screen name="Login" component={Login} />
<AuthStack.Screen name="Tabnavigator" component={Tabnavigator} />
</AuthStack.Navigator>
)
}
You don't have an initialRouteName Home in your Stack.Navigator. You need to point it to TabNavigator so that your code should look like this.
export default function Stacknavigator() {
return (
<Stack.Navigator
initialRouteName="TabNavigator"
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="TabNavigator" component={TabNavigator} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
)
}

Trying to push StackScreen in React Native

Whenever I activate the onPress method by tapping on a message, the MessageScreen component just re-renders rather than displaying ChatScreen. This happens even if I replace ChatScreen with any other screen. Any help on the matter is much appreciated.
App.js
<NavigationContainer ref={containerRef} initialState={initialNavigationState}>
<Drawer.Navigator>
<Drawer.Screen name="Feed" component={BottomTabNavigator} options={{swipeEnabled: false}} />
<Drawer.Screen name="Settings" component={SettingsStack} options={{swipeEnabled: false}} />
</Drawer.Navigator>
</NavigationContainer>
BottomTabNavigator
const BottomTab = createBottomTabNavigator();
export default function BottomTabNavigator({ navigation, route }) {
{...HomeStack Code}
{...ProfileStack Code}
const MyMessagesStack = createStackNavigator();
function MessagesStack() {
return (
<MyMessagesStack.Navigator initialRouteName={"Messages"}
screenOptions={{headerShown: false}}>
<MyMessagesStack.Screen name="Messages" component={MessagesScreen} />
<MyMessagesStack.Screen name="Chats" component={ChatScreen} />
</MyMessagesStack.Navigator>
);
}
return (
<BottomTab.Navigator initialRouteName={INITIAL_ROUTE_NAME} >
<BottomTab.Screen
name="Home"
component={HomeStack}
options={{title: 'Feed'}}
/>
<BottomTab.Screen
name="Messages"
component={MessagesStack}
options={{title: 'Messages'}}
/>
<BottomTab.Screen
name="Profile"
component={ProfileStack}
options={{title: 'Profile'}}
/>
</BottomTab.Navigator>
);
}
MessageScreen.js
//flatscreen to render message components
</View>
<FlatList
data={Data}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => props.navigation.navigate('Chats')} >
<Message
image={item.image}
name={item.name}
lastMessage={item.message}
timeStamp={item.timestamp}
opened
/>
</TouchableOpacity>
)}
/>
The reason your components are remounting is because there are components defined inside other components:
function BottomTabNavigator() {
// Here
function MessagesStack() {
// ...
}
// ...
}
You need to define them outside to avoid that:
function MessagesStack() {
// ...
}
function BottomTabNavigator() {
// ...
}

Categories