Reputation: 71
I am currently using expo router 2 with expo SDK49.
I would like to add a child route of a slot layout to be rendered as a stack layout - ie whole screen replaced with a back button. I can't seem to make it work and I can't seem to find anything in the docs.
I've produced a minimum example, attached below.
Any help would be appreciated.
Project structure
app
├── _layout.tsx
├── index.jsx
├── meow
│ └── test.tsx
└── woof
├── _layout.tsx
└── test.tsx
app/_layout.tsx
import { View, Text } from 'react-native'
import React from 'react'
import { Slot, Link } from 'expo-router'
import { SafeAreaView } from 'react-native-safe-area-context'
const Layout = () => {
return (
<SafeAreaView style={{flex: 1}}>
<Header />
<Slot />
</SafeAreaView>
)
}
const Header = () => {
return (
<View style={{flex: 1}}>
<Text> Header </Text>
<Link href='/meow/test' asChild>
<Text> Click here to render meow into slot </Text>
</Link>
</View>
)
}
export default Layout
app/index.jsx
import { View, Text } from 'react-native'
import React from 'react'
const Page = () => {
return (
<View>
<Text>Hello world</Text>
</View>
)
}
export default Page
meow/test.tsx
import { View, Text } from 'react-native'
import React from 'react'
import { Link } from 'expo-router'
const Page = () => {
return (
<View>
<Text>I am at meow, in a slot.</Text>
<Link href='/woof/test'>
<Text>Going to woof, should be a stack.</Text>
</Link>
</View>
)
}
export default Page
woof/_layout.tsx
import { View, Text } from 'react-native'
import React from 'react'
import { Stack } from 'expo-router'
const Layout = () => {
return (
<Stack />
)
}
export default Layout
woof/test.tsx
import { View, Text } from 'react-native'
import React from 'react'
const Page = () => {
return (
<View>
<Text>This is supposed to be a stack child!</Text>
</View>
)
}
export default Page
Here are the screenshots of each screen:
Clicked on meow, rendered into slot
From meow to woof with a stack layout but rendered into slot
I've also tried having a meow/_layout.tsx with a Stack layout which doesn't work either.
Is it even possible to do what I am trying to do with Slot? If not, are there any workarounds?
Thanks in advance,
Upvotes: 7
Views: 4941
Reputation: 26
I am currently using Expo SDK 51 and I encountered the same issue. I had to intervene with react-navigation
components. It worked as I wanted, but there are some differences. The stacks I created are added to the native stack, not Expo's stack. Even though these stacks are child stacks of Expo's stack, I was able to add them to the stack by using navigate('new-native-stack')
.
Here is the relevant code:
_layout.tsx
import { View, Text, Button } from 'react-native';
import React from 'react';
import { Slot, Stack, useNavigation } from 'expo-router';
import HomeHeader from '@/components/HomeHeader';
import { SafeAreaView } from 'react-native-safe-area-context';
type Props = {};
type MainScreenContext = {};
const MainScreenContext = React.createContext<MainScreenContext>({});
const Layout = (props: Props) => {
const navigation = useNavigation();
return (
<>
<HomeHeader />
<Slot />
</>
);
}
export default Layout;
A normal Expo stack under the layout
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import React from 'react';
import ChatsScreen from './ChatsScreen';
import SearchScreen from './SearchScreen';
type Props = {};
const Stack = createNativeStackNavigator();
const Layout = (props: Props) => {
return (
<Stack.Navigator initialRouteName="chats">
<Stack.Screen
name="search"
options={{
headerShown: false,
animation: 'none',
}}
component={SearchScreen}
/>
<Stack.Screen
name="chats"
options={{
headerShown: false,
animation: 'none',
}}
component={ChatsScreen}
/>
</Stack.Navigator>
);
}
export default Layout;
Now these two SearchScreen and ChatsScreen are stacks. When I go from chats to search, it pushes as a new stack. Chats will not unmount.
For this example, I navigate between these two screens in my HomeHeader.
Upvotes: 1