Closed cyberman-io closed 1 year ago
initial route name indicates which file (out of a stack) should always be rendered. If the app opens without a deep link, then the route will be /
which matches /index
and not /chat
. You can setup a redirect to move pages automatically if you want.
You can setup a redirect to move pages automatically if you want.
May I ask how?
I just wasted 6 hours today trying to do the same thing you wanted/thought you could do with the "initialRouteName" thing.
Eventually i found a way to do the redirect:
import { Redirect } from "expo-router";
const Index = () => {
return <Redirect href="/discussions" />;
};
export default Index;
I just wasted 6 hours today trying to do the same thing you wanted/thought you could do with the "initialRouteName" thing.
Eventually i found a way to do the redirect:
import { Redirect } from "expo-router"; const Index = () => { return <Redirect href="/discussions" />; }; export default Index;
Thanks! @EvanBacon consider adding this to the documentation. It's a very common use-case to have some nested (tabs, drawer) screen as the default home screen.
The redirect is not that straightforward. I spent a good amount of time trying to fix this with the initialRouteName
and couldn't figure it out
Just used expo-router v2 for the first time and also just spent hours getting the initial route to work.
So I think this is definitely worth adding to documentation, since it is a pretty common use case as @Savinvadim1312 pointed out. Also knowing react-navigation
, one would expect the property initialRouteName
to have an effect.
Utilizing the redirect seems to be a valid workaround, but in my case leads to the problem described in #740 .
For issue #740 , the fix is to wait for the navigation state to be ready. This is a preliminary fix for now, but I'm hoping the documentation will get better in the coming years:
import { View, Text } from "react-native";
import React from "react";
import { Redirect } from "expo-router";
import { useNavigation, useRootNavigation } from "expo-router";
import { LoadingScreen } from "../components/StyleComponents";
// index.tsx, referring to route /
export default function index() {
const navigation = useRootNavigation();
const [ready, setReady] = React.useState(false);
React.useEffect(() => {
if (!navigation?.isReady) return;
setReady(true);
}, [navigation?.isReady]);
if (ready) return <Redirect href="/whatever-route" />;
return <LoadingScreen />;
}
it's work for me both some nested screens
this is my file tree
app layout is Slot
Drawer layout incloud a Stack layout inside
[app]
/app/_layout.jsx
import { Slot } from "expo-router"; export default function RootLayout() { return <Slot />; }
/app/drawer/_layout.jsx init router is /app/drawer/stack/index.jsx, its also worker when i change initialRouteName to "pageOne" the default page will be /app/drawer/pageOne.jsx
import { Drawer } from "expo-router/drawer";
export default function DrawerLayout() { return ( <Drawer screenOptions={{ drawerType: "slide", overlayColor: "transparent", drawerStyle: { flex: 1, width: "65%", padding: 20, backgroundColor: "transparent", }, sceneContainerStyle: { backgroundColor: "transparent" }, }} initialRouteName="stack"
); }
/app/drawer/stack/_layout.jsx ```javascript import { Stack } from "expo-router";
export default function Layout() { return ( <Stack screenOptions={{ headerShown: false, }} /> ); }
> other pages is default template
```javascripts
import { View, Text } from "react-native";
import React from "react";
const pageOne = () => {
return (
<View>
<Text>pageOne</Text>
</View>
);
};
export default pageOne;
this is my packages version
"@react-navigation/drawer": "^6.6.3", "@react-navigation/native": "^6.0.2", "expo": "~49.0.8", "expo-font": "~11.4.0", "expo-linking": "~5.0.2", "expo-router": "2.0.0",
@lucacri @Savinvadim1312 maybe an unrelated question. But when having this redirect in initial component, for milliseconds I can see this initial screen of index.tsx. How would you implement it, so a user will not notice this redirect?
Same issue here @tonven.
Everyone keeps suggesting redirecting, but it causes a super ugly flash of the initial screen. Is there any real way to handle initial routes without a redirect? The Expo Router docs don't provide a solution to this or even mention anything about it. Is this just an artifact in local dev?
https://github.com/expo/router/assets/6440455/bb0863de-4c58-4db8-a4d3-54d00dd42e0d
@KornelKwiatkowski Why did you laugh at this? Say it to my face please
@lucacri @Savinvadim1312 maybe an unrelated question. But when having this redirect in initial component, for milliseconds I can see this initial screen of index.tsx. How would you implement it, so a user will not notice this redirect?
this is also a sad part.
@lucacri @Savinvadim1312 maybe an unrelated question. But when having this redirect in initial component, for milliseconds I can see this initial screen of index.tsx. How would you implement it, so a user will not notice this redirect?
Similar problem here. Before initial render I would like to determine if I need to show a login page or not. Right now I have to always go to the login page, check there if user is logged in, and then reroute. Which is not super nice, and has this flicker going on.
@MoSattler I agree that there should be a more straightforward way to define the initial route using the router. But I was still able to achieve what I needed using the splash screen module. Just show your splash or some placeholder loading screen until you determine where you'd like to send the user.
initial route name indicates which file (out of a stack) should always be rendered. If the app opens without a deep link, then the route will be
/
which matches/index
and not/chat
. You can setup a redirect to move pages automatically if you want.
@EvanBacon
What if there is no index.tsx?
Turns out I needed to use Static Options to reduce flickering. Dyanmic Options inherently will cause flickering.
if Redirect without flick the mobile screen it would good to take it in project
Hi everyone, I'm having a problem with expo router that I can't resolve, this is my file structure
My goal would be to redirect the user to the page (tabs)/index by default or after logging in, and this works correcty in development with expo-go app, but when i build the app for play store i can't be redirected to index page by default, in fact, after logging in, the splash screen appears and the redirect doesn't happen...
I tried to do a different redirect after login (activity/feelings page) and it works correctly, the problem is that i cannot reach the index page.
I'm using SDK 50 and expo router 3.4.8, this in my sign-in page (only redirect method):
const signInWithPassword = async () => {
setIsLoading(true);
const { data, error } = await supabase.auth.signInWithPassword({
email: username,
password: password,
});
if (error) {
Alert.alert(error.message);
setIsLoading(false);
} else {
await signIn(data.session.access_token, data.session.refresh_token);
setIsLoading(false);
console.log("After login, navigating to home page");
router.replace("/");
}
};
and this is my app/_layout.tsx
import type { Theme } from "@react-navigation/native";
import { DarkTheme, ThemeProvider } from "@react-navigation/native";
import { Stack } from "expo-router";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { AuthProvider } from "../context/AuthContext";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import * as SplashScreen from "expo-splash-screen";
import { useColorScheme } from "react-native";
export const unstable_settings = {
initialRouteName: "(tabs)",
};
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
export default function Root() {
const colorScheme = useColorScheme();
const DefaultTheme: Theme = {
dark: false,
colors: {
primary: "rgb(0, 122, 255)",
background: "rgb(255, 255, 255)",
card: "rgb(255, 255, 255)",
text: "rgb(28, 28, 30)",
border: "rgb(216, 216, 216)",
notification: "rgb(255, 59, 48)",
},
};
SplashScreen.hideAsync();
return (
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<AuthProvider>
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaProvider>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="sign-in" options={{ headerShown: false }} />
<Stack.Screen name="sign-up" options={{ headerShown: false }} />
<Stack.Screen
name="activity/note"
options={{ headerShown: false }}
/>
<Stack.Screen
name="activity/feelings"
options={{ headerShown: false }}
/>
<Stack.Screen name="modal" options={{ presentation: "modal" }} />
</Stack>
</SafeAreaProvider>
</GestureHandlerRootView>
</AuthProvider>
</ThemeProvider>
);
}
and finally this is my app/(tabs)/layout.tsx
import { useAuth } from "../../context/AuthContext";
import { useColorScheme, Text } from "react-native";
import { SimpleLineIcons } from "@expo/vector-icons";
import { AntDesign } from "@expo/vector-icons";
export default function TabLayout() {
const { isLoading, userToken } = useAuth();
const colorScheme = useColorScheme();
// You can keep the splash screen open, or render a loading screen like we do here.
if (isLoading) {
return <Text>Loading...</Text>;
}
// need to be able to access the (auth) group and sign in again.
if (!userToken) {
// On web, static rendering will stop here as the user is not authenticated
// in the headless Node process that the pages are rendered in.
return <Redirect href="/sign-in" />;
}
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: "#2f95dc",
headerShown: false,
tabBarShowLabel: false,
}}
>
<Tabs.Screen
name="index"
options={{
title: "Home",
tabBarIcon(props) {
return <AntDesign name="home" size={24} color={colorScheme === "light" ? (props.focused ? "black" : "gray") : (props.focused ? "white" : "#ced4da")} />
}
}}
/>
<Tabs.Screen
name="metrics"
options={{
title: "Metrics",
tabBarIcon(props) {
return <SimpleLineIcons name="graph" size={24} color={colorScheme === "light" ? (props.focused ? "black" : "gray") : (props.focused ? "white" : "#ced4da")} />
}
}}
/>
<Tabs.Screen
name="expert"
options={{
title: "Expert",
tabBarIcon(props) {
return <AntDesign name="staro" size={24} color={colorScheme === "light" ? (props.focused ? "black" : "gray") : (props.focused ? "white" : "#ced4da")} />
}
}}
/>
<Tabs.Screen
name="settings"
options={{
title: "Impostazioni",
tabBarIcon(props) {
return <AntDesign name="setting" size={24} color={colorScheme === "light" ? (props.focused ? "black" : "gray") : (props.focused ? "white" : "#ced4da")} />
},
}}
/>
</Tabs>
);
}
@EvanBacon I'm probably doing something wrong, but I can't figure out where.
Thanks everyone for the help!
I spent literally more than 2 days in this, and still can't figure it out, seems like this is very inconsistent as expo-router v3
import { queryClient } from "@/src/lib/query";
import { useReactQueryDevTools } from "@dev-plugins/react-query";
import FontAwesome from "@expo/vector-icons/FontAwesome";
import { QueryClientProvider } from "@tanstack/react-query";
import { useFonts } from "expo-font";
import * as SplashScreen from "expo-splash-screen";
import { useEffect } from "react";
import "react-native-gesture-handler";
import { ThemeProvider } from "styled-components";
import {
Inter_400Regular,
Inter_500Medium,
Inter_700Bold,
} from "@expo-google-fonts/inter";
import {
Nunito_400Regular,
Nunito_600SemiBold,
Nunito_700Bold,
} from "@expo-google-fonts/nunito";
import theme from "@/global/styles/theme";
import { AuthProvider } from "@/src/providers/auth";
import { ConfigNotificationContextProvider } from "@/src/providers/config-notifications-ctx";
import { UpdateProvider } from "@/src/providers/update-ctx";
import { DrawerToggleButton } from "@react-navigation/drawer";
import Drawer from "expo-router/drawer";
import { GestureHandlerRootView } from "react-native-gesture-handler";
export {
// Catch any errors thrown by the Layout component.
ErrorBoundary
} from "expo-router";
export const unstable_settings = {
// Ensure that reloading on `/modal` keeps a back button present.
initialRouteName: "(tabs)",
};
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
export default function RootLayout() {
useReactQueryDevTools(queryClient);
const [loaded, error] = useFonts({
SpaceMono: require("@assets/fonts/SpaceMono-Regular.ttf"),
Inter_400Regular,
Inter_500Medium,
Inter_700Bold,
Nunito_400Regular,
Nunito_600SemiBold,
Nunito_700Bold,
...FontAwesome.font,
});
// Expo Router uses Error Boundaries to catch errors in the navigation tree.
useEffect(() => {
if (error) throw error;
}, [error]);
// Hide the splash screen once the app is ready. (fonts loaded)
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return <RootLayoutNav />;
}
function RootLayoutNav() {
return (
<ThemeProvider theme={theme}>
<QueryClientProvider client={queryClient}>
<UpdateProvider>
<AuthProvider>
<ConfigNotificationContextProvider>
<GestureHandlerRootView style={{ flex: 1 }}>
<Drawer
screenOptions={{
headerShown: false,
drawerActiveTintColor: theme.colors.primary,
drawerInactiveTintColor: theme.colors.text,
swipeEdgeWidth: 80,
}}
initialRouteName="/"
>
<Drawer.Screen
name="index"
options={{
drawerLabel: "Tabs",
headerLeft: () => <DrawerToggleButton />,
drawerItemStyle: { display: "none" },
}}
/>
<Drawer.Screen
name="(tabs)"
options={{
drawerLabel: "Tabs",
headerLeft: () => <DrawerToggleButton />,
}}
/>
<Drawer.Screen
name="minha-conta"
options={{
drawerLabel: "Minha Conta",
headerLeft: () => <DrawerToggleButton />,
}}
/>
<Drawer.Screen
name="anunciar"
options={{
drawerLabel: "anunciar",
headerLeft: () => <DrawerToggleButton />,
}}
/>
<Drawer.Screen
name="+not-found"
options={{
drawerLabel: "anunciar",
headerLeft: () => <DrawerToggleButton />,
drawerItemStyle: { display: "none" },
}}
/>
</Drawer>
</GestureHandlerRootView>
</ConfigNotificationContextProvider>
</AuthProvider>
</UpdateProvider>
</QueryClientProvider>
</ThemeProvider>
);
}
even creating the index with redirect will not redirect to the correct route.
https://github.com/expo/router/assets/83284629/6332b5cf-29b5-47b9-8c34-95dde7d3226c
@ArthurDias01 This repo is for v2 and is only maintained for security purposes. If you are having an issue, please create a new issue at https://github.com/expo/expo
Also, reporting an issue with a code snippet of a single file does not met the criteria for a minimal reproduce-able repo. I can see from your video that the app is crashing from an error - but you have not provided me enough information to advise on what that error is. The best method is simply to share your repo so I can run the project.
I got it to work after some heavy debugging, clearing all cache, reinstalling all dependencies and creating a new clean build. @marklawlor thanks. Will try to be more specific to the issue next time.
I just wasted 6 hours today trying to do the same thing you wanted/thought you could do with the "initialRouteName" thing.
Eventually i found a way to do the redirect:
import { Redirect } from "expo-router"; const Index = () => { return <Redirect href="/discussions" />; }; export default Index;
the only issue I see with this is the transition / animation.
I just wasted 6 hours today trying to do the same thing you wanted/thought you could do with the "initialRouteName" thing. Eventually i found a way to do the redirect:
import { Redirect } from "expo-router"; const Index = () => { return <Redirect href="/discussions" />; }; export default Index;
the only issue I see with this is the transition / animation.
Yeah, the user can see a white screen before redirect
Acabo de perder 6 horas hoy tratando de hacer lo mismo que querías / pensabas que podías hacer con lo de "initialRouteName".
Finalmente encontré una manera de hacer la redirección:
import { Redirect } from "expo-router"; const Index = () => { return <Redirect href="/discussions" />; }; export default Index;
This worked for me...
Is there no fix to this?
It seems like I’m not the only one having this problem. I’m using < Slot /> with initialRouteName, but it doesn’t seem to have any effect. It always shows '/' instead of '/home'.
Same. I'm creating a stack navigator
And when I navigate to /onboarding/questions I'd like to be on /onboarding/questions/0 by default to have an id = 0. For now I navigate to /onboarding/questions, the component [id].tsx
is properly read but with id being undefined, I default it to 0 manually for now but I'm not confortable with that
Summary
i expect the initial route will be /chat/index but the initial route always /index in the route directory File system:
Minimal reproducible example