Ash Gharibyan
Ash Gharibyan

Reputation: 141

Expo Router going back on a dynamic route

I am navigatiing from /home to /listing/1 then from there I am navigating to /listing/2, when I go back I expect to go back to /listing/1 but it is going back to /home.

Why is that, If it is a dynamic route, expo router doesnt add it to the history and replaces it? How can I fix this?

This is my folder structre

enter image description here

this is my main layout:

 <Stack>
             <Stack.Screen
                name="index"
                options={{
                  headerShown: false,
                }}
              />
              <Stack.Screen
                name="+not-found"
                options={{
                  headerShown: false,
                }}
              />
              <Stack.Screen name="(auth)" options={{ headerShown: false }} />
              <Stack.Screen name="(main)" options={{ headerShown: false }} />
              <Stack.Screen name="listing/[id]" options={{ headerShown: false }} />
              <Stack.Screen name="chef/[id]" options={{ headerShown: false }} />
              <Stack.Screen name="category/[id]" options={{ headerShown: false }} />
            </Stack>

This is my back button, but it still doesnt work if I slide back

import React from "react";
import { TouchableOpacity } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { useRouter, useNavigation } from "expo-router";

interface BackButtonProps {
  size?: number;
  color?: string;
  className?: string;
}

const BackButton: React.FC<BackButtonProps> = ({ size = 24, color = "gray", className = "" }) => {
  const router = useRouter();
  const navigation = useNavigation();

  // Check if we can go back
  const canGoBack = navigation.canGoBack();

  return (
    <TouchableOpacity
      onPress={() => {
        if (canGoBack) {
          // Use router.back() if we can go back
          router.back();
        } else {
          // If we can't go back, go to the home screen
          router.replace("/");
        }
      }}
      className={`rounded-full ${className}`}>
      <Ionicons name="chevron-back" size={size} color={color} />
    </TouchableOpacity>
  );
};

export default BackButton;

Versions I use

    "@react-navigation/native": "^6.0.2",
    "expo-linking": "~7.0.4",
    "expo-router": "~4.0.16",=
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "react-native": "0.76.6",

Upvotes: 0

Views: 316

Answers (2)

Fredrik
Fredrik

Reputation: 3293

You can solve it by adding a getId prop to the <Stack.Screen />. For example:

<Stack.Screen
  name="ad/[slug]"
  options={{ headerShown: false }}
  getId={({ params }) => params.slug}
/>

By default, the Stack navigator removes duplicate screens when pushing a route that is already in the stack. For example, if you push the same screen twice, the second push will be ignored. You can change this push behavior by providing a custom getId() function to the <Stack.Screen>.

Ref: https://docs.expo.dev/router/advanced/stack/#custom-push-behavior

Upvotes: 0

AJAY B
AJAY B

Reputation: 1

  • When navigating between /listing/1 and /listing/2, expo-router may replace the current route in the history stack instead of adding a new entry.

  • This happens because the route paths only differ by a dynamic id, which some configurations may treat as a single screen.

  • so When router.back() is called, it looks at the history stack. If the navigation history only has /home or /listing/2 (replacing /listing/1), it will go back to /home.

To avoid it u can use router.push(/whatever) to the stack. instead of router.replace(/whatever).

const navigateToListing = (id) => {
  const router = useRouter();
  router.push(`/listing/${id}`); 
};

Upvotes: 0

Related Questions