48

I have made a custom component for header title(stack navigator)which shows user name along with some image. On this page I have to edit the username and on success Update it in header as well

So my question is How to change/update title dynamically?

shwetap
  • 621
  • 1
  • 6
  • 14
  • For React Navigation 5.x refer - https://stackoverflow.com/questions/62080817/dynamically-change-header-title-on-react-navigation-5-x – Rizwan Dec 17 '20 at 15:43

12 Answers12

38

This can be done using the navigation props.

You can use this.props.navigation.state.params in a component to set a new property. Call:

navigation.setParams({ param: value })

See the documentation on headers for more detail.

Tyler Whitman
  • 524
  • 5
  • 11
36

For React Navigation version 1.x, 2.x, 3.x and 4.x, you can simply change the header by using the method shown in the code below, or the one in the original documentation: React Navigation - using params in the title

     static navigationOptions = ({ navigation }) => {
        const edit = navigation.getParam('edit', false);
        if(edit){
          return {
            headerTitle: 'Edit Page',
          };
        }else{
          return {
            headerTitle: 'Normal Page',
          };
        }
     };

For version 5.x and above, you may refer to the code below. Here are the links for the official documentation and example in expo.

 import * as React from 'react';
    import { View, Text, Button } from 'react-native';
    import { NavigationContainer } from '@react-navigation/native';
    import { createStackNavigator } from '@react-navigation/stack';

    function HomeScreen({ navigation }) {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>Home Screen</Text>
          <Button
            title="Go to Profile"
            onPress={() =>
              navigation.navigate('Profile', { name: 'Custom profile header' })
            }
          />
        </View>
      );
    }
    
    function ProfileScreen({ navigation }) {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>Profile screen</Text>
          <Button title="Go back" onPress={() => navigation.goBack()} />
        </View>
      );
    }
    
    const Stack = createStackNavigator();
    
    function App() {
      return (
        <NavigationContainer>
          <Stack.Navigator>
            <Stack.Screen
              name="Home"
              component={HomeScreen}
              options={{ title: 'My home' }}
            />
            <Stack.Screen
              name="Profile"
              component={ProfileScreen}
              options={({ route }) => ({ title: route.params.name })}
            />
          </Stack.Navigator>
        </NavigationContainer>
      );
    }
    
    export default App;
TOPKAT
  • 6,667
  • 2
  • 44
  • 72
luke77
  • 2,255
  • 2
  • 18
  • 30
31

In React 5.0 or above you could do the following if you want to use a Class Component:

 componentDidMount() {
   this.props.navigation.setOptions({
     title: `Your Updated Title`,
   })
 }
Kewal Shah
  • 1,131
  • 18
  • 29
  • this is the best one, this did what I needed easily – Arsalan Ahmad Ishaq Jan 26 '21 at 07:18
  • I have an issue working with this solution, I used useRoute to pass the objects as params to my app's detail screen but when I use code above or in general adding option and using it in app.js for some reason it wont work also not sure how to pass route params to the app.js. Sorry if it looks dumb kindda new to the react and programming – navidabasi May 20 '21 at 00:33
20

With React Navigation 5 and React Navigation 6 you can do this like this, set Params in your component

props.navigation.navigate("ProductDetailScreen", {
      productId: itemData.item.id,
      productTitle: itemData.item.title,
    });

And display it

<Stack.Screen
      name="ProductDetailScreen"
      component={ProductDetailScreen}
      options={({ route }) => ({ title: route.params.productTitle })} // what 
need to add
/>

or you can do this in your component with useEffect hooks

useEffect(() => {
    props.navigation.setOptions({
      title: productTitle,
    });
  }, [productTitle, props.navigation]);
Slava Vasylenko
  • 838
  • 1
  • 9
  • 14
11
 navigation.setOptions({ title: 'Updated!' })

Reference.

Muhammed Ozdogan
  • 5,341
  • 8
  • 32
  • 53
4

the code that shows in the part below is for the version of react-navigation 2.x

you can try the following:

in my case I have the configuration of navigation in a file called, app-navigator.js

const ChatStackNavigator = createStackNavigator(
    {
        People: ListPeopleScreen, // People Screen,
        Screen2: Screen2
    },
    {
        initialRouteName: 'People'
        navigationOptions: ({navigation}) => ({
            header: <AppBar title={navigation.getParam('appBar', {title: ''}).title}/>
        }),
        cardStyle: {
            backgroundColor: 'white'
        }
    }
);

The screen file would be as follows:

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {List, ListItem} from 'react-native-elements';

class ListPeopleScreen extends Component {

    list = [
        {
            name: 'Amy Farha',
            avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg',
            subtitle: 'Vice President'
        },
        {
            name: 'Chris Jackson',
            avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
            subtitle: 'Vice Chairman'
        }
    ];

    componentDidMount() {
        this.props.navigation.setParams({
            appBar: {
                title: 'Clientes'
            }
        });
    }

    render() {
        return <List
            containerStyle={{marginBottom: 30}}
        >
            {
                this.list.map((item) => (
                    <ListItem
                        roundAvatar
                        avatar={{uri: item.avatar_url}}
                        key={item.name}
                        title={item.name}
                    />
                ))
            }
        </List>
    };
}

export default connect(null)(ListPeopleScreen);

NOTE: in my case I am using redux, and the library of components react-native-elements

Juanes30
  • 2,398
  • 2
  • 24
  • 38
3

In version 3.x and 4.x this can be done using static navigationOptions function,

For class compenents,

class MyComponent extends Component {
  static navigationOptions = ({navigation}) => {
    return {
      title: navigation.getParam('title', 'Fallback title');
    };
  }

  updateHeader = () => {
    // dynamically update header
    navigation.setParams({title: 'MyComponent'});
  }

  render() {
    // call updateHeader on click of any component
  }
}

For functional components,

const MyComponent = (props) => {
  const updateHeader = () => {
    // dynamically update header
    navigation.setParams({title: 'MyComponent'});
  }

  // call updateHeader on click of any component
}

MyComponent.navigationOptions = ({navigation}) => ({
  title: navigation.getParam('title', 'Fallback title'),
})
Aravind Vemula
  • 1,571
  • 17
  • 22
2

for react navigation Version: 5.x

   const ProductDetailScreen = props => {
       const { productId } = props.route.params;
       const { productTitle } = props.route.params;

       props.navigation.setOptions({ title: productTitle });

       return  (
            <View>
                <Text>{productId}</Text>
            </View>
        );
     };

for react navigation Version: 5.x

Bilal Ahmad
  • 781
  • 8
  • 10
  • 1
    We get a warning for this, cannot update a component from inside the function body of a different component. – Vasanth Feb 19 '21 at 12:29
1

For version 4, this is work for me.

    const HistoryScreen: NavigationStackScreenComponent<any, any> = (props) => {
  const { navigation } = props;

  useEffect(() => {
    let device = props.navigation.getParam("device");
    if(device) {
        navigation.setParams({title: `History - ${device.name}`})
    }
  }, []);

    ... render view

    HistoryScreen.navigationOptions = ({
      navigationOptions,
      navigation,
    }) => ({
      headerTitle: navigation.getParam("title") ? navigation.getParam("title") : "History"
    });
}
Bob
  • 71
  • 4
0
function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="OrdersScreen"
          component={OrdersScreen}
          options={{ title: 'My Orders' }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
Keshav Gera
  • 10,807
  • 1
  • 75
  • 53
0

For React-Navigation v3, I used the following command to change the title of a stack:

Class component:

this.props.navigation.setParams({ title: res.title });

Function component:

props.navigation.setParams({ title: res.title });
Mohammad Goldast
  • 367
  • 2
  • 4
  • 14
0

If you use createStackNavigator you can do like this:

createStackNavigator({
  // For each screen that you can navigate to, create a new entry like this:
  Profile: {
    // `ProfileScreen` is a React component that will be the main content of the screen.
    screen: ProfileScreen,
    // When `ProfileScreen` is loaded by the StackNavigator, it will be given a `navigation` prop.

    // Optional: When deep linking or using react-navigation in a web app, this path is used:
    path: 'people/:name',
    // The action and route params are extracted from the path.

    // Optional: Override the `navigationOptions` for the screen
    navigationOptions: ({ navigation }) => ({
      title: `${navigation.state.params.name}'s Profile'`,
    }),
  },

  ...MyOtherRoutes,
});

from the doc

call it like this:

navigation.navigate('Profile', {_id: item._id, name: item.screenName})}
Boris Mitioglov
  • 1,092
  • 4
  • 16
  • 32