Open ep1kt3t0s opened 1 year ago
Only when both unstable_settings
and initialRouteName
in the Stack
is used then it works. 🤷♂️
I am running into this when deep linking from one tab with its own stack to another tab with its own stack. There is no back button for the deep linked page although, unstable_settings.initialRouteName
and initialRouteName
on the deep linked Stack are configured.
import { Redirect } from "expo-router";
const Index = () => {
return <Redirect href="/onboarding" />;
};
export default Index;
i know it's not a proper solution. for now am going with this.
check out : https://github.com/expo/router/issues/428
I'm able to use this to impact the router history with groups. My initial problem was I couldn't figure out how to have proper pop/push animations. I always wanted anything in (auth) group to pop and anything in (tabs) to push. Turned out I just had to export this in the root layout:
export const unstable_settings = {
initialRouteName: '(auth)',
}
Well, I'm running into the same issue. After running a few investigations, if you console.log each route component, you see that the components are really mounting, but the redirect is being redirected again to the index of (tabs), for some unknown reason.
The render order is "initial route" > "login" > "(tabs)/index". I tested both reloading and from a fresh start. Clearing the cache with -c had no effect. However, if you don't navigate when the app loads, and you do a fast refresh from a change in the code, the route properly initiates in the correct route. However, any attempt to open the app defaults to tabOne in the template.
Navigating from the Expo Go app, you go straight to "(tabs)/index".
package.json
"expo": "~50.0.4",
"expo-router": "~3.4.6",
Same issue, I set initialRouteName
and in unstable_settings
on every _layout
(unclear which to use) and none have any effect, the initial route is always "/"
The React Navigation -> Expo Router migration guide seems to imply that the initialRouteName
on navigators like <Stack>
is a no-op - it's whatever index
is for a navigator that determines the initial route.
And it seems that the same property in unstable_settings
is purely there to determine where the back button goes to on an initial render in the case of something like deep linking - it doesn't seem to dictate anything to do with what renders first on an ordinary boot of the app.
With this in mind I think (tabs)/index
as the initial route would be the expected behaviour because (tabs)
is a group and hence doesn't contribute to a routing URL segment, therefore (tabs/index)
is effectively index
? And if there is no index
it just looks for the first screen at the top level alphabetically?
The docs could probably be a bit clearer that initialRouteName
on the navigators don't have any effect? And unstable_settings.initialRouteName
seems a bit of a misleading name. Idk
I have a case where my new app goes to (auth) >. index.tsx instead of (tabs) > index.tsx. initialRouteName doesnt work
I have a case where my new app goes to (auth) >. index.tsx instead of (tabs) > index.tsx. initialRouteName doesnt work
In that case, specify the initial route like this, (auth)/index
.
I have a case where my new app goes to (auth) >. index.tsx instead of (tabs) > index.tsx. initialRouteName doesnt work
In that case, specify the initial route like this,
(auth)/index
.
But I wanted to go to (tabs)/index.tsx. I set the initialRouteName up to "(tabs)". I have up and used redirections
Very confusing.
Not only it doesn't work, but initialRouteName
is accepted on <Stack />
, <Slot />
, and unstable_settings
yet does nothing.
I encountered the same issue with initialRouteName
not working properly in my Expo Router setup. Here is how I solved it:
app/_layout.tsx
_layout.tsx
file of the app directory, I kept the splash screen on while loading fonts via expo-font
.import { useEffect, useState } from "react";
import { SplashScreen } from "expo";
import * as Font from "expo-font";
import { Stack } from "expo-router";
//keep the splash screen on
SplashScreen.preventAutoHide();
export default function RootLayout() {
const [fontsLoaded, setFontsLoaded] = useState(false);
const [isAuthenticated, setIsAuthenticated] = useState(null);
const router = useRouter();
useEffect(() => {
const loadFonts = async () => {
await Font.loadAsync({
// Add your custom fonts here
"Roboto-Regular": require("./assets/fonts/Roboto-Regular.ttf"),
});
setFontsLoaded(true);
};
const checkAuthStatus = async () => {
// Your logic to check if the user is authenticated
const status = await getAuthStatusFromYourService();
setIsAuthenticated(status);
};
loadFonts();
checkAuthStatus();
}, []);
if (!fontsLoaded) {
return null;
}
return <Stack screenOptions={{ your-prefered-config }} />;
}
app/index.tsx
:<Redirect>
component from expo-router
to navigate to the desired route or route group (tabs) or (main) or (auth) or (whatever-route)
.useRootNavigationState()?.key
hook from Expo Router is not undefined my way of checking is the root navigation is ready
.useRootNavigationState()?.key
is not undefined, then it returns the <Redirect>
component.import { Redirect, Slot, Stack, useRootNavigationState } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import { useEffect, useState } from "react";
import { ActivityIndicator, Platform, StatusBar } from "react-native";
import colors from "@/constants/colors/index";
import { Provider } from "react-redux";
import { store } from "@/redux/store";
import useCustomFonts from "@/hooks/useCustomFonts";
import useAuthStatus from "@/hooks/useAuthStatus";
import ScreenLayout from "@/components/styles/layout/screen-layout";
import CView from "@/components/custom/CView";
import useTheme from "@/utils/hooks/theme/useTheme";
export const unstable_settings = {
initialRouteName: "(test)",
};
export const platform = Platform.OS;
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
export default function RootLayout() {
const isAuthenticated = useAuthStatus();
const theme = useTheme();
const navigation = useRootNavigationState();
const [isReady, setIsReady] = useState(false);
useEffect(() => {
// check if navigation state is ready to prevent flickering when redirecting
if (!navigation?.key) return;
// if navigation state is ready, hide splash screen
SplashScreen.hideAsync();
setIsReady(true);
}, [navigation?.key]);
if (!isReady || isAuthenticated === "loading") {
return (
<ScreenLayout>
<CView _className="flex-1 items-center justify-center">
<ActivityIndicator size="large" color={colors.accent[theme]} />
</CView>
</ScreenLayout>
);
}
return <Redirect href={"/(test)"} />;
}
Notice I'm rather hiding the splash screen in this file, this is to solve the flickering issue caused by the redirect.
You just have to wait for navigation state to be ready (thus useRootNavigationState()?.key must not be undefined)
Same here
I think all solutions are confused. My solutions:
Set the redirect
prop of Stack.Screen
to true for the index page.
app/_layout.tsx
import { useFonts } from "expo-font";
import { Stack } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import { useEffect } from "react";
import "react-native-reanimated";
SplashScreen.preventAutoHideAsync();
export default function RootLayout() {
const [loaded] = useFonts({
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
});
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return (
<Stack >
<Stack.Screen name="index" options={{ headerShown: false }} redirect />
<Stack.Screen name="login" options={{ headerShown: false }} />
<Stack.Screen name="about" options={{ headerShown: false }} />
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
);
}
Index page will redirects to first sibling page
@osmanemin adding redirect did the trick 🎉🎉
I just created an index
folder at the same level as _layout
and added a redirect inside it.
import { type Href, Redirect } from 'expo-router'
import { useUser } from '@/hooks/use-user'
export default function RedirectPage() {
const { user } = useUser()
const href = (user ? '(tabs)' : '(auth)') as Href
return <Redirect href={href} />
}
If initialRouteName
worked you wouldn't need this, but it's also a solution.
@andres-dos-santos you are a true hero. It works perfectly. Thank you!
What is the status of this will you guys make the initialRouteName
or we will keep flash screening people :D.
Ran into the same issue, it would be good if the prop initialRouteName
is removed while it is not functioning as expected
We ended up using react navigation directly which after a small amount of setup was much easier than trying to solve these issues and more intuitive regarding nested navigators
I don't think expo-router
is stable and production ready unless this issue is resolved
Which package manager are you using? (Yarn is recommended)
npm
Summary
On a fresh Expo project with tabs and Typescript, the
unstable_settings.initialRouteName
has no effect.I also tested
<Stack initialRouteName=...>
and it also has no effect.Basically, any directory with parenthesis
(something)
alphabetically at the top becomes the default route, unless there is anindex
directory.This doesn't correlate with what's described in the documentation: https://expo.github.io/router/docs/features/routing/#layout-settings
Minimal reproducible example
Steps to reproduce:
Step 1, Environment
Step 2, Testing the effect
Duplicate
(tabs)
directory and rename the duplicate to(a)
Update some text in(a)/index.ts
Add<Stack.Screen name="(a)" options={{ headerShown: false }} />
into the<Stack>
Result:
(a)
will be the default route withoutunstable_settings.initialRouteName
is updated. You can set anything tounstable_settings.initialRouteName
, there is no effect.