I'm using react-native-navigation with:
a custom animated app loading screen
my home screen
I created a Stack.Navigator as follows:
<Stack.Navigator
initialRouteName="AnimatedAppLoader"
>
<Stack.Screen
name="AnimatedAppLoader"
component={AnimatedAppLoader}
/>
<Stack.Screen
name="Home"
component={Home}
/>
</Stack.Navigator>
My AnimatedAppLoader waits that the app is ready then navigate to the Home screen through:
navigation.navigate('Home');
The problem is that the Home screen becomes a child of AnimatedAppLoader screen and users can go back to the loader screen.
I tried to disable back button and back gestures but this solution does not seem proper since android users can still go back with the system back button.
Is there a proper way to set my Home screen as the root parent of my app?
use navigation.replace('Home'); replace will replace the current screen with a new one rather than adding a new screen
you can read more at the props
https://reactnavigation.org/docs/navigation-prop/
Related
How can I navigate to a bottomtab screen rather than a stack screen? The goal is to take the user to the main home page onPress of the sign in button. I initially created a Stack.Screen and added the homescreen component but that crashed the header and the bottom tab navigation and there was also the back button in the header which isn't supposed to be because the home screen is the main screen. Is there a way to navigate to the bottom tab screen from the sign in component? I'm a beginner by the way and also not so good at using stack overflow
if you're using react router than this may possible with useNavigate() and Link. Also you can add custom javascript window.location.href ="/pagename"
Usage of useNavigate() before return of function-
const navigate = useNavigate()
onClick = (e)=>(
e.preventDefault()
navigate('/home')
)
Usage of Link inside body-
<Link to="/home"></Link>
Usage of custom javascript inside body-
<button onClick = (()=>window.location.href="/home"))>Click me</button>
Hope you'll like the answer. But if you still face any issue just lemme know.
I suggest you to try an Authentication flow approch written by 'React-Navigator' API.
The main idea of that is using 2 Navigators.
Stack Navigator for 'Login'
Tab Navigator for pages which logged in users can see
However, to make this flow available, you need to add Global State Management library like Redux / React Context to handle which navigator is showing. Once the state is set, the app will auto select the navigator used. You don't need to call any function for navigation.
<NavigationContainer>
<Stack.Navigator>
{
!redux.isLoggedIn ?
<Stack.Group>
<Stack.Screen
name="auth"
component={Auth}
/>
</Stack.Group>
:
<Stack.Group>
<Stack.Screen
name="home"
component={YourHomeTabNavigator}
/>
</Stack.Group>
}
</Stack.Navigator>
</NavigationContainer>
I have a problem during the logout in my react native app. I set many navigators to handle multiple navigation flow, but when I try to logout from the app, the login screen appears two times.
I try to explain how I organize my navigators below:
I created a TabNavigator which handle the main navigation of the app if a user is logged in otherwise I show the LoginNavigator which handle login, registration and password forgot screens.
I use a state, stored on redux for handling the login state (isLoggedIn).
<NavigationContainer>
{isLoggedIn ? <TabNavigator/> : <LoginNavigator/>}
</NavigationContainer>
Into the TabNavigator I set other navigator for handling page flow in each sections, like the exemple below:
TabNavigator
Screen X
Navigator1
Screen A
Screen B
Navigator2
Screen C
Screen D
Screen Y
Into the Screen C I'd like to logout from the app, so I call an action which set the isLoggedIn state to false.
What happens is that the Login screen (the inital screen of LoginNavigator) appears, but it suddently slides off and another Login screen appears.
It happens only from nested screen, instead if I try to logout from Screen X or Screen Y it works perfectly fine.
Does anyone encounter this problem? How can I solve this behaviour?
I solved this behaviour!
Instead of showing the correct navigator using a ternary operation, base on redux state, I wrap TabNavigator and LoginNavigator inside a custom stack navigator with a WaitingScreen.
I set the WaitingScreen as inital route and I moved the logic about which route between MainNavigator and LoginNavigator has to be shown inside WaitingScreen, in a useLayouEffect with isLoggedIn as dependecy.
<NavigationContainer>
<Stack.Navigator
initialRouteName={NavConst.LOADING}
screenOptions={{
headerShown: false,
contentStyle: {
backgroundColor: Color.primary600,
},
animation: "none",
}}
>
<Stack.Screen name={NavConst.LOADING} component={WaitingScreen} />
<Stack.Screen name={NavConst.LOGIN_NAV} component={LoginNavigator} />
<Stack.Screen name={NavConst.MAIN_NAV} component={MainNavigator} />
</Stack.Navigator>
</NavigationContainer>
and inside the WaitingScreen:
useLayoutEffect(() => {
isLoggedIn
? navigation.navigate(NavConst.MAIN_NAV);
: navigation.navigate(NavConst.LOGIN_NAV);
}, [isLoggedIn]);
I can't seem to figure out what is causing this code to not work on Android. It works well on iOS. It is a custom tab bar which lives inside a screen of the "normal" bottom tab bar. It has three screens and when switching between them I can see that things are happening under the hood, it's just that only the last tab screen is shown. All of the screens are being rendered and using useFocusEffect I can see that the screens are getting focused when the buttons are pressed, but they are not shown. So it's like they´re hidden behind the last tab screen.
The code is pretty much exactly taken from the example in the react-navigation guide (and I have also tried this with the exact example code):
https://reactnavigation.org/docs/custom-navigators
except that the top level <view>s had to switch places for the tab bar to be visible.
The tab navigator is then embedded like this (I have just replaced the actual names with numbers):
const 4Tab = createCustomTabNavigator<4ParamList>()
export default function 4TabNavigator() {
return (
<4Tab.Navigator initialRouteName="1">
<4Tab.Screen name="1" component={1Navigator} />
<4Tab.Screen name="2" component={2Navigator} />
<4Tab.Screen name="3" component={3Navigator} />
</4Tab.Navigator>
)
}
which in turn is embedded like so (4TabNavigator):
const Tab = createBottomTabNavigator() // Normal tab bar
const TabStack: React.FC<Props> = props => {
return (
<Tab.Navigator
initialRouteName={TabRouteName.1}
screenOptions={tabScreenOptions}>
<Tab.Screen name={TabRouteName.1} component={1Navigator} />
<Tab.Screen name={TabRouteName.2} component={2Navigator} />
<Tab.Screen name={TabRouteName.3} component={3Stack} />
<Tab.Screen
name={TabRouteName.4}
component={4TabNavigator}
options={{ lazy: true }}
/>
<Tab.Screen name={TabRouteName.5} component={5Navigator} />
</Tab.Navigator>
)
}
I'm not sure if this is an issue with react-navigation at all, but I also don't know what else could be wrong. I have looked through react-navigation's GitHub issues, and of course here on SO, but to no avail.
Let's suppose I have a TabNavigator. In a screen, I'm able to navigate to a modal screen (full screen modal => it's placed outside the TabNavigator stack) and go back but, if I refresh the browser in the modal screen (F5), I'm unable to go back. The go back button disappears.
I can even reproduce it with the Expo init typescript tabbed default project.
Video describing the problem: https://recordit.co/4PULNdWRPT
Code: https://github.com/MADSENSE/Madsense.ReactNative.Sample/tree/master
Does anywone knows how to fix this / any workaround?
This is what you expect while navigating a web app. Whoever, you can force the icon to show and navigate to wherever you want manually.
example:
<Stack.Screen
name="..."
component={...}
options={navigation => ({
headerLeft: props => <IconComponent onPress={navigation.navigate("...")} />,
})}
/>
Also, you have to navigate to a screen by its name navigation.navigate("...") because you can't tell from where the user went to your screen.
I have a react native app using react navigation. My app has 3 different stacks = { ROOT, AUTH, USER }.
Stacks ROOT & AUTH are managed by authentication flow, if there's a token I switch to ROOT otherwise AUTH. That works fine. In my USER stack, is where I place "universal" screens (screens that can be accessed either from root or auth stack). Let's consider one of my USER stack screen is ValidateUserAccount (which is accessed through a link from the email). The problem comes when for example I open my app and I'm in the LoginScreen, in the AUTH stack. On iOS, the go back has the previous screen title. Since the previous screen it's in another stack , it shows "< auth", instead of "< login". Same happens with the ROOT. If I'm at HomeScreen, in the ROOT stack and I open the ValidateUserAccount, the go back button is "< root".
<MainStack.Navigator
screenOptions={{
headerShown: false
}}>
{accessToken ? (
<MainStack.Screen
name="root"
component={BottomTabNavigator}
/>
) : (
<MainStack.Screen
name="auth"
component={AuthenticationStack}
/>
)}
<MainStack.Screen
name="user"
component={UserStack}></RootStack.Screen>
</MainStack.Navigator>
How can I manage to display the go back with the previous screen title instead of previous stack title, eventhough it's in another stack?
Is it possible? or the only solution is to hide the go back title?