I use https://reactnavigation.org/ and my app has a register process consisting of several screens:
First, the user has to enter his first name ("FirstNameView")
Second, the user has to enter his last name ("LastNameView")
...
If the user closes the app in the LastNameView and opens it later again, the app sends a request to the backend to fetch the current user data. Depending on this data, the user is navigated to the right screen via the initialRouteName property:
<MainStack.Navigator
initialRouteName="LastNameView"
>...
I have a back button on every screen which does navigation.goBack(), which obviously not works if the user just opens the app again and I direct him to the right View without pushing other screens to it.
One approach that I could think of is removing the navigation.goBack() functionality and replacing it with navigation.navigate("nameOfPreviousView"). However, this has the drawback that native "back" functionality of e.g. Android would not work.
How can I handle a case like this? Can I somehow create a fake history with my initialRouteName approach?
Yes you can create previous route history without navigating there.
In NavigationContainer initialize initialState like
let initialState = initialRoute = {
index: 1, // to load the second screen which is LastNameView
routes: [
{
name: 'FirstNameView',
},
{
name: 'LastNameView',
},
],
};
Like
<NavigationContainer initialState={initialState}> {/* ... */} </NavigationContainer>
To explore more about initialState check description here https://reactnavigation.org/docs/navigation-container/#initialstate
Related
I'm using a Drawer Navigator as my base with history and have a Home screen and a Notifications screen.
Now for a deeplink myapp://notifications i want to have a history like Home->Notifications so that on pressing physical back btn the user is taken to Home instead of closing the app.
However it seems this does not work with backBehaviour set as history as now Home is never added when opening deeplink.
Is there any way to update the history so that it always has Home as initial screen?
(I have set Home as Initial screen in my linking config but that does not help)
The reset action allows resetting the navigation state to the given state.
Try to run this dispatch if your app opened using the deep link
(Untested) example:
import { CommonActions } from '#react-navigation/native';
navigation.dispatch((state) => {
// Add the home route to the start of the stack
const routes = [{ name: 'Home' }, ...state.routes];
return CommonActions.reset({
...state,
routes,
index: routes.length - 1,
});
});
Read more about reset action
I realize why this occurring but am trying to figure out the best way to go about getting the required behavior:
Let's say I have a tab navigator and inside those tabs I have stack navigators. When I first open the app I am in the Home tab. Now let's say a push notification comes in and I handle that and say go to this screen in the profile stack navigator. The screen is not usually the first screen in the navigator but because I have not navigated to the profile screen via the tab navigator the initial screen is not loaded so it's the first in the stack. If I call navigation.pop it will not be handled by a navigator because their is no screen to go back to in the profile navigator.
I figured I could just call navigation.navigate('Profile') and it does navigate to that screen but it doesn't pop the initial screen so clicking the tab by default will now make the first screen the base screen until the app is restarted.
If I call navigation.goBack() I won't run into the above problem but I won't be able to always ensure that the 'Profile' screen is the place it goes back to.
Ideally I'd like some way to say push this screen into this stack and then push this screen. So when pop is called it will always show that users profile screen.
** EDIT **
After looking through some docs I found that I can do the following:
navData.dispatch(() => {
navData.navigate('Home', {
screen: 'ProfileScreen',
});
navData.navigate('Home', {
screen: 'ProfileScreen',
params: {
screen: 'ViewPostScreen',
params: { shouldPlay: true },
},
});
});
Though I get the following warning: Possible unhandled Promise rejection: TypeError: undefined is not an object 'action.target'
I'm also using this logic in another location of my app with a different screen and works in development but not in production. Looking for suggestions on to best handle the above situation.
I have an app that starts with a loader screen where I determine whether the user is an admin or not. This screen navigates to a BottomTabNavigator, but I want to show different tabs based on whether the user is admin or not. I looked at the documentation for custom navigators but this still requires the navigator to be created outside the class, so I can't use the params. I also tried this:
export default class BottomTabNavigator extends Component {
render() {
const BottomTabComponent = createBottomTabNavigator({
...
});
return (
<BottomTabComponent {...this.props} />
);
}
}
But that doesn't work either (seems like I shouldn't pass the navigation prop down). Removing {...this.props} is also no good because then I would have to wrap the component in an app container, but that is also not right, so I'm not sure how to proceed.
I'm actually doing a login system and when my user is logged, the login component has to send data to my main screen but I don't really understand how to do it.
Actually I've this when user is logged :
User.username = data.username;
User.id = responseJson.id;
User.token = responseJson.token;
this.props.navigation.navigate('Main', { User: User });
User is where everything is saved and it works.
Data is sended to Main a Switch Navigates inside an AppContainer :
export default createAppContainer(createSwitchNavigator(
{
Auth: { screen: AuthStack, navigationOptions: { tabBarVisible: false } },
Main: { screen: MainStack },
},
{
initialRouteName: "Auth"
}),
);
so it goes on Mainstack who's a bottomTabNavigator and works like that :
const MainStack = createBottomTabNavigator(
{
Services: {
screen: Home,
navigationOptions: {
tabBarLabel:"Services",
tabBarIcon: ({ tintColor }) => (
<Icon name="home" size={30} color="#0033CC" />
)
},
},
I know it's not complete I've other screens not only Services, just wanted to avoid too long function on paste.
So is that possible to send this data "User" to my Home screen ?
I'm open to any suggestion or answer, that's my first react Native project so there is maybe some mistakes :)
You'll probably want to persist the user data in the app (save it in the storage for when the user leaves the app then enters he stays logged in). That's why react-navigation has the switchNavigator (the one you are using). In order to persist data, you can use the AsyncStorage to save the user data and in the switch navigator constructor check whether the user data is already available in the storage or not then decide whether to navigate to the app or the authentication page. In fact React Navigation provides an example on this: https://reactnavigation.org/docs/en/auth-flow.html . Since you're new to RN, here's an extra tip on managing data: you can use a State in every component that is only for that specific component (which is also reactive), you can use global data (store) shared between all the components in the app (check react redux/flux/mobx), you can share data from parent components to children components by passing data/functions in the props (aka attributes), and you can use the new React context api to use a provider (also like a store shared between parent and children components)
I've made something maybe a bit more understandable :
I get my user data in component login from an external api and it works well. To go from login to home I'm using this :
this.props.navigation.navigate('Main', { User: User})
So it goes on Main who opens Mainstack Screen who's a bottomTabNavigator and if I don't do any mistakes my User data that I've sent is on this Mainstack but I don't know how to get it and how to share it to the other components.
Every component got his own js file, there is only the App container and Authstack/Mainstack that are on the same file.
Hope you understood it !
I have a react-native app with two screens, Home and Details. Using react-navigation, Ive set the Stack navigator as following
const RootStack = createStackNavigator(
{
Home: FormComponent,
Details: DetailScreen
},
{
initialRouteName: "Home",
headerMode: "none"
}
);
Home contains a form, which once submitted, navigates to the Details screen with relevant data (using navigation.navigate("Details",{some data})). At this point, if I exit the app, and then open it again, the Details screen loads, with all the data preserved(Instead of the Home screen). I logged the navigation object data (this.props.navigation.) and it prints like the app was never closed.
Am I missing something here? Im new to React Native and Navigation, but from what I understand this is not expected behaviour.
Tried uninstalling app and rebuilding. This resets the app and Home screen loads. If I try reinstalling without uninstalling, back to same behaviour.
Tried also manually forcing navigation.goBack() on ComponentWillUnmount() but no difference.
This should've been a comment but sadly i don't have enough reputation.
Could you check if you haven't accidentally set a persistenceKey as a navigator prop?
https://reactnavigation.org/docs/en/state-persistence.html