expo / router

[ARCHIVE]: Expo Router has moved to expo/expo -- The File-based router for universal React Native apps
https://docs.expo.dev/routing/introduction/
1.36k stars 113 forks source link

"Layout children must be of type Screen" inside a _layout file Expo Router 2 #789

Closed JulianKingman closed 1 year ago

JulianKingman commented 1 year ago

Which package manager are you using? (Yarn is recommended)

yarn

Summary

I'm trying to create a DrawerNavigator with no header for my root layout, just the menu button. Here's what I have:

// app/_layout.tsx
export default function DrawerLayout() {
  return (
    <Drawer
      screenOptions={{
        drawerPosition: 'right',
        headerRight(props) {
          return <DrawerToggleButton {...props} />;
        },
        headerLeft(props) {
          return null;
        },
        headerTransparent: true,
        headerTitle: '',
      }}
    >
      <SafeAreaView>
        <Drawer.Screen name="index" />
      </SafeAreaView>
    </Drawer>
  );
}

It needs a SafeAreaView, because headerTransparent: true removes the safe area. Having done the above, I get the error: Layout children must be of type Screen, all other children are ignored. To use custom children, create a custom <Layout />. Update Layout Route at: "app/_layout" I believe this is what I'm doing above? I might be missing something basic, and I suspect this is so, because it's been a big struggle to implement a drawer navigator, which is not complicated.

Minimal reproducible example

Put into an empty repo with expo 49 and Expo Router 2

// _layout.tsx
import { DrawerToggleButton } from '@react-navigation/drawer';
import Drawer from 'expo-router/drawer';
import { SafeAreaView } from 'react-native-safe-area-context';

export default function DrawerLayout() {
  return (
    <Drawer
      screenOptions={{
        drawerPosition: 'right',
        headerRight(props) {
          return <DrawerToggleButton {...props} />;
        },
        headerLeft(props) {
          return null;
        },
        headerTransparent: true,
        headerTitle: '',
      }}
    >
      <SafeAreaView>
        <Drawer.Screen name="index" />
      </SafeAreaView>
    </Drawer>
  );
}
// index.tsx
import { Text, View } from 'react-native';

export default function Home() {
  return (
    <View style={{ flex: 1, backgroundColor: 'red' }}>
      <Text>HOME!</Text>
    </View>
  );
}
marklawlor commented 1 year ago

The children of <Drawer /> must be a <Drawer.Screen>. You can either add <SafeAreaView /> inside the screen or simply add a margin to the Drawer header.

The React Navigation docs explain now to do this without <SafeAreaView /> https://reactnavigation.org/docs/native-stack-navigator/#headertransparent