Have a stack navigator always render initialRoute - javascript

I'm building a react native app and I'm using react-navigation package. I have a tab navigator for the app and each tab has a stack navigator in it. Something like this:
const HomeStack = StackNavigation({
Info: {screen: Info},
Main: {screen: Main}
})
const SearchStack = StackNavigation({
Search: {screen: Search},
SearchResult: {screen: SearchResult}
})
TabNavigation({
Home: {screen: HomeStack},
Search: {screen: SearchStack}
})
So let's say I did a search and I'm now on SearchResult screen. I then go back to Home screen by pressing home tab. Now when I go back to search tab it shows me the SearchResult screen. Is there a way to force react-navigation to always render a Search screen when you go to it from the Tab?
I made a project on snack to illustrate this https://snack.expo.io/rkMzWoh17

use initial route name like this in searchstack navigation like this
{
initialRouteName: 'Search',
}

You can use something like this inside every stack screen.
const Search = ({ navigation }) => {
useLayoutEffect(() => {
const blur = navigation.addListener('blur', () => {
navigation.popToTop();
});
}, []);
}
This pops the stack to the initial screen everytime you navigate away.
More information here: https://reactnavigation.org/docs/navigation-events

Related

how to hide back button in React-navigation/react-native

I would like to hide the Back button in the top-left corner, but I don't have any idea how to do it with react-navigation or react-native.
Just tried to use static navigationOptions = { header: null } but the < Back button was still alive.
I was using Modal and it works, but I want to know how to hide < Back button without using Modal.
Thank you in advance!
Using headerLeft: () => <></> works great in iOS, but in Android was still displaying the default back button.
I was able to hide it by adding the headerBackVisible: false on the screenOptions of the Stack Navigator or you could include it on the options for every Stack Screen.
More info at https://reactnavigation.org/docs/native-stack-navigator/#headerbackvisible
I suppose you're using a StackNavigator and that you don't want a header.
You need to use headerMode: none in the StackNavigatorConfig.
For example:
const ModalStack = createStackNavigator(
{
HomeScreen: { screen: Home },
ModalScreen: { screen: Modal },
},
{
headerMode: 'none',
mode: 'modal',
}
);
More info in the react-navigation docs.
It depends upon the react navigation version you're using, try this
const ModalStack = createStackNavigator(
{
HomeScreen: { screen: Home },
ModalScreen: { screen: Modal },
},
{
headerMode: 'none',
header: null
}
);
if it is StackNavigator default config, go to StackNavigator:
defaultNavigationOptions: {
header: null,
},
const Stack = createStackNavigator();
<Stack.Navigator screenOptions={{headerShown: false}}>
createStackNavigator is a function that returns an object containing 2 properties: Screen and Navigator. Both of them are React components used for configuring the navigator.
Now below Stack.Navigator, you can place your screens using <Stack.Screen name="Home" component={HomeScreen} />. In name, you can give any name, and in component give the name of your component.

Nothing is rendered after navigation in react-native

I am using SwitchNavigator from React-navigation for Authentication in React-native app. In the Authorized Section, I want to show a side Drawer for showing options like settings and log out. Entering into the Authorized section by clicking the button in tabs section user should be able to go to details section of an album. For that, I am using StackNavigator.
Issue:
After Authentication, Once I navigate to a section with Side Drawer in which stack navigator is present, nothing is rendered once navigated to Authorized section. Even the Test screen is mounted(checked through componentDidMount) nothing is displayed.
const Stages = createMaterialTopTabNavigator({
testStage1: { screen: TestScreen },
testStage2: { screen: TestScreen },
testStage3: { screen: TestScreen },
testStage4: { screen: TestScreen },
})
const AuthorizedSectionRouteConf={
navigation:{
stages: {
screen : Stages,
},
details : {
screen: DetailsScreen,
}
},
navigationOptions:{
headerLeft:null
}
}
const AuthorizedSectionNavigator =
createStackNavigator(AuthorizedSectionRouteConf.navigation);
const Config = {
navigation: {
UnauthorizedSection: {
screen: ({navigation}) => <LoginScreen navigate={navigation.navigate}/>,
navigationOptions:{
header:null,
mode:'modal'
}
},
AuthorizedSection: {
screen: createDrawerNavigator({
Home:{
screen: ({navigation}) => <AuthorizedSectionNavigator screenProps={{drawerNavigator:navigation}} />
}
})
},
TestSection: TestScreen
}
}
export default AppNavigator = createSwitchNavigator(Config.navigation);
Navigation after navigation:
this.props.navigate('AuthorizedSection')
==> nothing is visible after this.
However, If I navigate to TestScreen after Authentication which is simple text on screen
it rendered properly.
this.props.navigate('TestSection')
==> working properly
Figured out that there is no space for the component to render. Fixed it by setting the flex property for the parent container.

DrawerNavigator: DrawerItem other than screen

I want a simple functionality of logging out from drawer item press. For that i have done this:-
const HomeNavigator = DrawerNavigator(
{
Splash: { screen: SplashScreen }
}
)
This adds an item in drawer and on clicking it app navigates to splash screen. But with this method i could not achieve whole functionality of logging out. i.e:-
Clearing the screen stack so that on back press app shouldn't go back to screen with drawer.
App should navigate from splash to login screen after logging out.
My above solution not letting me do both these things. Is there a better way to achieve my requirement?
Update
My Navigation structure so far is somewhat like this:-
StackNavigator(
Splash: {screen: SplashScreen},
Login: {screen: LoginScreen},
Home: {screen: HomeScreen},
)
HomeNavigator = DrawerNavigator(
Logout: {screen: SplashScreen}
)
HomeScreen{
render(){
return <HomeNavigator navigation={this.props.navigation} />;
}
}
You can see i am using SplashScreen in both navigators. In stack it's the first screen while in drawer it's used for logging out. but when i navigate from drawer screen to splash i lose the StackNavigator that i created before for splash to login navigation. Can you suggest me any better way to do it?
You can call this function in the componentWillMount(){} of the Splash Screen:
clearStack = (routeToGo) => {
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: routeToGo })
]
})
this.props.navigation.dispatch(resetAction)
}
Importing {NavigationActions} from react-navigation.
You can also create a custom drawer navigator by using the contentComponent prop in the DrawerNavigatorConfig, in which you can change the onPress of the navItems to do whatever you want, like calling the function to clear your stacks.
UPDATE: on your Splash Screen
componentWillMount(){
this.clearStack('Login')
}

React Navigation Nested Stacks, accessing Root stack

Is there a way to access a root stack navigator from an inner stack navigator? For example:
const Root = StackNavigator(
{
Login: {
screen: Login,
},
TabNav: {
screen: TabNav
}
}
);
const TabNav = TabNavigator(
{
Content: {
screen: Content,
},
Settings: {
screen: SettingsStack
}
}
);
Within that SettingsStack screen I have a logout button. How would I access the Root Stack to navigate back to Login? Rather than that inner stack in the Tab Navigation just pushing to the login page within the child stack.
From TabNav in StackNavigator pass a function as a screenProp to TabNavigator . Use the function whenever you want to logout. Since SettingsStack is a navigator inside another navigator pass the props into SettingsStack to make it work.

react native navigate with different files

As a newbie in react-native i'm trying find a way to use react-navigation with different files without a navbar to navigate (for example just click on a button in the login view to enter the main view, clicking on log out button return to login view).
With react-navigation i made a global component 'Nav' and i placed in the main AppRegistry call:
AppRegistry.registerComponent('myApp', () => Nav);
While in the Navigator.js:
export const Nav = StackNavigator({
Login: { screen: LoginView },
AddStream: { screen: AddStreamView },
});
When i run
react-native run-android
i get the first view loaded under a white space (it should be the navigator, that i don't want in my app)
Now how can i remove the Nav from the view and how can i change View onPress a button component in another file?
There is another package that fill better my desire?
From the docs, setting the the headerMode to none should do the trick. This will hide the header on all of the screens defined in that StackNavigator. Example:
const Nav = StackNavigator({
Login: { screen: LoginView },
AddStream: { screen: AddStreamView },
},{
headerMode: 'none',
});
If you want to control the visibility of the header so that it appears on some of the screens but not all of them, then you can set headerMode to screen and for each individual screen set [the navigation prop for header: { visible: false }. See docs here. For example, if you are creating the screen component in another file, it might look like this:
// In the main file:
const Nav = StackNavigator({
Login: { screen: LoginView },
AddStream: { screen: AddStreamView },
},{
headerMode: 'screen',
});
// Hidden for your Login screen:
export default class LoginView extends Component {
static navigationOptions = {
header: { visible: false }
}
// etc...
}
// Visible for your AddStream screen:
export default class AddStreamView extends Component {
static navigationOptions = {
header: { visible: true }
}
// etc...
}
Edit: missed the second part of your question.
For navigating to a different screen, you really should go through the Hello World tutorial as it explains it. Specifically, this section. Relevant example code from the tutorial:
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>Hello, Chat App!</Text>
<Button
onPress={() => navigate('Chat')}
title="Chat with Lucy"
/>
</View>
);
}
In your case, 'Chat' would be either 'Login' or 'AddStream'.

Categories