javascriptreact-nativeexpo

Expo React native Stack headerRight with custom component does not redirect using Link


I am starting with Expo and React Native. I want to redirect to a custom page using Stack in Expo and React native. The Link work in the first example, but in the headerRight does not. I check the stack documentation but it does not say about using redirect in the headerRight. But it does say that accepts React component. The Link works outside of Stack and I also have a menu in index.js where I have more links and all of them work just fine with the stack functionality.

Can you help me to understand why the headerRight button may not be working? Thank you for your help.

_layout.js

import { Stack, Link } from "expo-router";
import { View, Text, StyleSheet, Pressable } from "react-native";

export default function Layout() {
  return (
    <View className="flex-1 bg-black">
      <Link href="/about" asChild>  <-- Working
        <Pressable>
          <Text style={styles.buttonText}>About</Text>
        </Pressable>
      </Link>
      <Stack
        screenOptions={{
          headerStyle: {
            backgroundColor: "#888",
          },
          headerTintColor: "#fff",
          headerTitleStyle: {
            fontWeight: "bold",
          },
          headerRight: () => (
            <Link href="/about" asChild> <-- Does not work
              <Pressable>
                <Text style={styles.buttonText}>About</Text>
              </Pressable>
            </Link>
          ),
        }}
      >
        <Stack.Screen name="index" options={{ title: "Home" }} />
        <Stack.Screen name="about" options={{ title: "About" }} />
      </Stack>
    </View>
  );
}

about.js

import { ScrollView, Text } from "react-native";

export default function About() {
  return (
      <Text classname="text-white text-white/900" style={{ marginBottom: 40 }}>
        Lorem ipsum..
      </Text>     
  );
}

index.js

import { useCameraPermissions } from "expo-camera";
import { Link } from "expo-router";
import { useEffect, useState } from "react";
import { StyleSheet, Text } from "react-native";
import { View, TouchableOpacity } from "react-native";

export default function Index() {
  return (
       <View className=" bg-orange-300 items-center justify-center">          
          <Link href="/camera" asChild>
            <TouchableOpacity style={styles.button}>
              <Text style={styles.buttonText}>Escaner</Text>
            </TouchableOpacity>
          </Link>
      ...many other...
          <Link href="/about" style={styles.buttonText} asChild>
            <TouchableOpacity style={styles.button}>
              <Text style={styles.buttonText}>About</Text>
            </TouchableOpacity>
          </Link>
        </View> 
  );
}

package.json

{
  "name": "codebar-app",
  "version": "1.0.0",
  "main": "expo-router/entry",
  "scripts": {
    ...
  },
  "dependencies": {    
    "@react-native-async-storage/async-storage": "^2.1.2",
    "@react-native-picker/picker": "2.9.0",
    "expo": "~52.0.19",
    "expo-camera": "~16.0.10",
    "expo-constants": "~17.0.8",
    "expo-linking": "~7.0.5",
    "expo-router": "~4.0.19",
    "expo-status-bar": "~2.0.1",
    "nativewind": "^2.0.11",
    "react": "18.3.1",
    "react-native": "0.76.5",    
    "react-native-safe-area-context": "4.12.0",
    "react-native-screens": "~4.4.0",    
    "react-native-web": "~0.19.13"
  },

Solution

  • This is an android specific issue and has been an open issue for React native Expo since last year, which might be coming from this issue from react-native-screens. This is also tracked in react-native/navigation.

    Basically, Link and other Pressables are not working inside headerRight.

    Link might not work but I see people making do with a pressable and navigating using a callback. They are using onPressIn

    Based on feasibility, you might also use react-native-gesture-handler