58

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?

1

15 Answers 15

41

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;
Sign up to request clarification or add additional context in comments.

4 Comments

How to change the header title dynamically on react navigation 5.x
@Rizwan I have added the example for version 5.x
Any suggestion how can we do it in class component? I am able to show the headerRight using this.props.navigation.setOptions but onPress doesn't trigger the class component.
React navigation version 5.x stackoverflow.com/a/73502663/8238512
40

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.

4 Comments

@mehulmpt Sorry about that, they changed the docs. I updated it.
With react 5.0 or above you can simply do this.props.navigation.setOptions({title: newTitle})
@KewalShah it's actually: props.navigation.setOptions({ headerTitle: newTitle, }); currently
38

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`,
   })
 }

2 Comments

this is the best one, this did what I needed easily
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
24

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]);

Comments

13
 navigation.setOptions({ title: 'Updated!' })

Reference.

2 Comments

Perfect answer.
For me I need headerTitle. navigation.setOptions({ headerTitle: "Updated!" });
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

Comments

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'),
})

Comments

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

1 Comment

We get a warning for this, cannot update a component from inside the function body of a different component.
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"
    });
}

Comments

0
function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="OrdersScreen"
          component={OrdersScreen}
          options={{ title: 'My Orders' }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Comments

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 });

Comments

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})}

Comments

0

When using react-native with expo you can access globalSearchParams and get the title from screen params.

import {Stack, useGlobalSearchParams} from 'expo-router';

export default function StackLayout() {
    const global = useGlobalSearchParams();

    return (
        <Stack>
            <Stack.Screen
                name="myscreen"
                options={{
                    title: "" + (global?.screenTitle ? global.screenTitle : ''),
                    headerShown: true,
                }}
            />
        </Stack>
    )

And when navigating:

import {router} from 'expo-router';
...
router.replace({pathname: '/scoreboard', params: {gameId, gameName}});

Comments

0

When using react-native with expo you can access globalSearchParams and get the title from screen params.

import {Stack, useGlobalSearchParams} from 'expo-router';

export default function StackLayout() {
    const global = useGlobalSearchParams();

    return (
        <Stack>
            <Stack.Screen
                name="myscreen"
                options={{
                    title: "" + (global?.screenTitle ? global.screenTitle : ''),
                    headerShown: true,
                }}
            />
        </Stack>

And when navigating:

import {router} from 'expo-router';
...
router.replace({pathname: '/myscreen', params: {screenTitle: 'My screen title'}});

Comments

0

If you're using expo-router's Stack Navigator (version 51+ to be precise) then you can refer this page of official docs to configure the header bar dynamically for an individual route.

Example

My app folder's structure is like this

app
 - _layout.tsx
 - index.tsx // renders Customer.tsx
 - customer_details.tsx  // renders CustomerDetails.tsx

In _layout.tsx I use Stack Navigator like this.


import {Stack} from 'expo-router'

const RootLayout = () => {
  return <Stack/>
}

The index.tsx file looks like this

Customer.tsx -> which is one of the routes

<Link
  style={[styles.card, { backgroundColor: theme.colors.inputBackground }]}
  asChild
  href={{
    pathname: "/(app)/customer_details",
    params: { customerName: item.name },
  }}
>
 <Pressable>
  .........

When I press the link, it renders the below customer_details.tsx screen which is CustomerDetails.tsx component like this where I am able to dynamically render the customerName in this screen's header title which I had defined in my Customer.tsx screen above

const CustomerDetails = () => {
  const { customerName } = useLocalSearchParams();
  return (
    <View>
      <Stack.Screen
        options={{
          headerTitle: customerName ? (customerName as string) : "Transactions",
        }}
      />
      <Text>CustomerDetails</Text>
    </View>
  );
};

export default CustomerDetails;

const styles = StyleSheet.create({});

Hope that helps!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.