How to change screen using stackNavigation in React Native? - react-native

I have one screen which in header consists button to go to another screen.
I have already model here, but it doesn't work: As shown below I want to change the screen from RecipeList to NewRecipeForm using Button in header
const AppStackNavigator = createStackNavigator({
List: {
screen: RecipesList,
navigationOptions: {
title:'RecipesList',
headerLeft: (
<Button onPress={()=>this.props.navigation.navigate('NewRecipeForm')}>
<Text>+</Text>
</Button>
)
}},
NewRecipeForm: {screen: CreateRecipeForm,
navigationOptions: {title:'Add new recipe'}},
Details: {screen: RecipesDetails, navigationOptions: {title:'RecipeDetails'}},
export default class App extends React.Component {
render() {
return <AppStackNavigator initialRouteName='List' />;
}
}
I hope that you will help me with solution

You may use your stack navigator as like below, you can able to destructure your navigation property while giving your navigationOptions property as well in the createStackNavigator itself
const AppStackNavigator = createStackNavigator({
List: {
screen: RecipesList,
navigationOptions: ({navigation}) => { //destructure the navigation property here
return {
title: 'RecipesList',
headerLeft: (
<Button onPress={() => navigation.navigate('NewRecipeForm')}>
<Text>+</Text>
</Button>
)
}
}
},
NewRecipeForm: {
screen: CreateRecipeForm,
navigationOptions: { title: 'Add new recipe' }
},
Details: { screen: RecipesDetails, navigationOptions: { title: 'RecipeDetails' } }
});

You cannot access the props of your component in headerLeft, but you can directly use the navigation like this :
<Button onPress={()=> navigation.navigate('NewRecipeForm')}>

You can use following code inside your RecipesList Component instead of having it inside createStackNavigator(). See this Snack for full implementation.
static navigationOptions = ({ navigation }) => {
return {
headerTitle: "RecipesList",
headerLeft: (
<Button
onPress={() => navigation.navigate('NewRecipeForm')}
title="+"
/>
),
};
};

Related

Access to react stack navigation inside header component

Inside the SamplePage, I could access navigation via this.props.navigation.
Inside the SampleHeader component, I have a button.
How I can access navigation in onPress action in button, declared inside SampleHeader?
const AppStackNavigator = createStackNavigator({
SamplePage: {
screen: SamplePage,
navigationOptions: {
title: 'title',
headerStyle: styles.headerStyle,
headerTintColor: styles.headerTintColor,
headerTitleStyle: styles.headerTitleStyle,
headerRight: <SampleHeader></SampleHeader>
}
}
...
you can try this:
SamplePage: {
screen: SamplePage,
navigationOptions: ({ navigation }) => ({
....
headerRight: <SampleHeader navigation={navigation}/>
....
})
}
Try the below code and see if its works , you can pass navigation as props to SampleHeader :
const AppStackNavigator = createStackNavigator({
SamplePage: {
screen: SamplePage,
navigationOptions: {
title: 'title',
headerStyle: styles.headerStyle,
headerTintColor: styles.headerTintColor,
headerTitleStyle: styles.headerTitleStyle,
headerRight: <SampleHeader navigation={this.props.navigation}></SampleHeader>
}
}
or you can create your own SampleHeader as that, and when you call it in a page suppose SamplePage you can add like,
class SamplePage extends Component {
render(){
return(
<SampleHeader navigation={this.props.navigation} />
)
}
}
and then after that , you can access on buttonCLick by this.props.navigation.
Hope it helps. feel free for doubts

How do I conditionally render a header in a Stack Navigator for React Native Navigation?

I would like my initial page to NOT contain a header. However, I would like a header to appear on each subsequent page. Right now my current stackNavigator looks like this:
const AppNavigator = createStackNavigator(
{
HomeScreen: HomePage,
SecondPage: SecondPage,
Account: Account,
About: About,
},
{
initialRouteName: 'HomeScreen',
headerMode: 'none',
navigationOptions: {
headerVisible: false,
},
},
);
export default createAppContainer(AppNavigator);
Here is the basic boilerplate for my second page:
const SecondPage: () => React$Node = () => {
return (
<>
<StatusBar barStyle="dark-content" />
<View style={styles.body}>
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>This is the Secondpage</Text>
</View>
</View>
</>
);
};
export default SecondPage;
You have three ways of doing this using navigationOptions:
1) Directly when you define your navigator:
createStackNavigator({
{
HomeScreen: {
screen : HomePage,
navigationOptions: {header : null}
},
SecondPage: SecondPage,
Account: Account,
About: About,
},
{ ... } //your navigationOptions
})
2) Directly inside the screen as said by Shashank Malviya. Only if you aren't using a functional component.
3) Return defaultNavigationOptions as a function and use navigation state:
createStackNavigator({
{ ... }, //your RouteConfigs
{
initialRouteName: 'HomeScreen',
headerMode: 'none',
defaultNavigationOptions : ({navigation}) => navigation.state.routeName === "HomePage" && {header: null}
},
})
Can be written on every component before render
static navigationOptions = ({ navigation }) => {
const { state } = navigation
return {
headerVisible: true // can be true or false
}
}

React Navigation drawer doesn't display the title of the current page

I created 2 pages namely Home and Profile and added these two pages to createDrawerNavigation. And then added this drawer navigation to a stack navigator. Now when I try to display the title on the header of the current page. I'm unable to do it.
Here is my code.
Tried DefaultNavigationOptions and got the props value of navigator but doesn't work that way.
const MenuStack = createDrawerNavigator(
{
HomePage: {
screen: Home
},
ProfilePage: {
screen: Profile
}
},
{
drawerWidth: Math.round(Dimensions.get("window").width) * 0.75,
contentOptions: {
activeTintColor: theme.colors.accent
}
}
);
const AppStack = createStackNavigator(
{
MenuStack: {
screen: MenuStack
}
},
{
defaultNavigationOptions: ({ navigation }) => {
return {
headerLeft: (
<Icon
style={{ paddingLeft: 10 }}
onPress={() => navigation.toggleDrawer()}
name="bars"
size={30}
/>
),
headerRight: (
<Icon
style={{ paddingRight: 10 }}
onPress={() => navigation.toggleDrawer()}
name="search"
size={30}
/>
),
headerTitle: navigation.state.routeName,
headerStyle: {
backgroundColor: theme.colors.accent
}
};
}
}
);
export const createRootNavigator = (signedIn = false) => {
return createAppContainer(
createSwitchNavigator(
{
SignedIn: {
screen: AppStack
},
SignedOut: {
screen: WelcomeStack
},
SignInAndOut: {
screen: AuthStack
}
},
{
initialRouteName: signedIn ? "SignedIn" : "SignedOut"
}
)
);
};
I added a headerTitle property in the createStackNavigator but I tell the "menustack" as the title for every page.
Expected the title of the page on the header.
You have 2 options:
1. Render your own header component in each screen
You can render a header inside your screens, either a custom one or one from a component library such as react native paper.
function Home() {
return (
<React.Fragment>
<MyCustomHeader title="Home" />
{{ /* screen content */ }}
</React.Fragment>
);
}
2. Create a stack navigator for each screen that needs to have header
const MenuStack = createDrawerNavigator({
HomePage: {
screen: createStackNavigator({ Home })
},
ProfilePage: {
screen: createStackNavigator({ Profile })
}
});
Keep in mind that while this requires less code, it's also less performant.

How to avoid overriding 'title' of the header in TabNavigator and its children screens? (react-navigation)

I want to set the title of the TabNavigator as 'Stylebook' with a button.
However, the screens which are children of TabNavigator change the 'title'. I think it's overriding the 'title' prop. How can I avoid it?
This is TabNavigator (my TabBar is in the StackNavigator)
export default TabNavigator(
{
Category: {
screen: StylebookCategoryScreen
},
All: {
screen: StylebookAllScreen
}
} ,{
navigationOptions: ({ navigation }) => ({
title: 'Stylebook',
headerRight: (
<Button onPress={() => navigation.navigate('Wardrobe')}
title="Wardrobe"
/>
)
})
});
StylebookAllScreen is almost identical with StylebookCategoryScreen.
class StylebookAllScreen extends Component {
static navigationOptions = {
title:'All'
}
render() {
return (
<View>
<Text>StylebookALLScreen</Text>
<Text>StylebookALLScreen</Text>
</View>
)
}
}
export default StylebookAllScreen;
I can also change whole structure of the navigator, if I can fix this.
Thanks!
You have to put your StylebookAllScreen component into a StackNavigator and then put that into your TabNavigator. Putting it into a StackNavigator allows you to set props like
navigationOptions: ({navigation}) => ({
title: "Stylebook",
}),
With headerLeft or headerRight you can add a Component (such as a Button to the left/right of your headline.
Try something like this:
const StylebookStack = StackNavigator({
StylebookAllScreen: {
screen: Map,
navigationOptions: ({ navigation }) => ({
title: "Stylebook",
headerTitleStyle: {
....
},
}),
},
});
And then put that into your TabNavigator
export default TabNavigator(
{
Category: {
screen: StylebookCategoryScreen
},
All: {
screen: StylebookStack // <--- HERE
}
} ,{
navigationOptions: ({ navigation }) => ({
title: 'Stylebook',
headerRight: (
<Button onPress={() => navigation.navigate('Wardrobe')}
title="Wardrobe"
/>
)
})
});

Add hamburger button to React Native Navigation

I'm very new to React-Native so I definitely may be missing something. But all I want to do is add a hamburger type button to a settings page in the main Navigation bar. I have set up a link in the main part of that works the way I want hamburger button to work.
Screenshot
import React from 'react';
import { AppRegistry, Text, View, Button } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
headerLeft: <Button onPress={ WHAT GOES HERE?? } title= "=" />
};
render() {
const { navigate } = this.props.navigation;
return (
<Button
onPress={() => navigate('Settings')}
title="Link to Settings" />
);
}
}
class Settings extends React.Component {
static navigationOptions = {
title: 'Settings',
headerLeft: <Button title= "=" />
};
render() {
return <Text>Hello, Settings!</Text>;
}
}
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
Settings: { screen: Settings}
});
AppRegistry.registerComponent('NavPractice', () => SimpleApp);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Having this, you're very close to the solution.
static navigationOptions = {
title: 'Welcome',
headerLeft: <Button onPress={ WHAT GOES HERE?? } title= "=" />
};
A little-known fact is that navigationOptions accepts a function that returns navigation options. That function accepts some props, navigation one of them. Know this, adjust your code a little.
static navigationOptions = function(props) {
return {
title: 'Welcome',
headerLeft: <Button onPress={() => props.navigation.navigate('DrawerOpen')} title= "=" />
}
};
check this link with same issue https://github.com/react-community/react-navigation/issues/1539
check navigationOptions
navigationOptions: ({ navigation }) => ({
title: 'Schedules', // Title to appear in status bar
headerLeft: <Icon name="menu" size={35}
onPress={ () => navigation.navigate('DrawerOpen') } />
from
const SchedulesStack = StackNavigator({
Schedules: {
screen: SchedulesScreen,
navigationOptions: ({ navigation }) => ({
title: 'Schedules', // Title to appear in status bar
headerLeft: <Icon name="menu" size={35} onPress={ () => navigation.navigate('DrawerOpen') } />
})
}
});
const Homestack = StackNavigator({
Home: {
Screen: Home
navigationOptions: ({ navigation }) => ({
title: 'Home', // Title to appear in status bar
headerLeft: <Icon name="menu" size={35} onPress={ () => navigation.navigate('DrawerOpen') } />
})
}
});
const Root = DrawerNavigator({
Home: {
screen: HomeStack,
navigationOptions: {
title: 'Home' // Text shown in left menu
}
},
Schedules: {
screen: SchedulesStack,
navigationOptions: {
title: 'Schedules', // Text shown in left menu
}
}
}
})
In the above code it seems you are adding options to the sidebar and navigating to the sidebar menus.
//sidebar menu no.1
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
headerLeft: <Button onPress={//action taken when option in the menu bar is clicked} title= "//the title of the screen where you will navigate and the sidebar menu lable" />
};
render() {
const { navigate } = this.props.navigation;
return (
<Button
onPress={() => navigate('Settings')}
title="Link to Settings" />
);
}
}
In this way you can create as many drawer options as you can.. now how to combine drawer options:
//react navigation provides you with DrawerNavigator API
const MyApp = DrawerNavigator({
Home: {
screenA: HomeScreen ,
},
Settings: {
screen: MySettingScreens,
},
});
The drawer also comes with a prop that is screenProps={/* this prop will get passed to the screen components and nav options as props.screenProps */}, like this :
<MyApp
screenProps={/* this prop will get passed to the screen components and nav options as props.screenProps */}
/>
Following are the props that react navigator provide to open/close drawer.
this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer
You can also set the drawer style according to you, like this:
drawerWidth - Width of the drawer
drawerPosition - Options are left or right. Default is left position.
contentComponent - By default there is no scrollview available in the drawer. In order to add scrollview in the drawer you need to add contentComponent in the configuration.
contentOptions - As the name suggest these are used to give color to the active and inactive drawer items (label).
Cheers :)