Lỗi "A navigator can only contain 'Screen' components as its direct children" xảy ra khi sử dụng @react-navigation/native (v5+). Nguyên nhân: **Con trực tiếp của <Stack.Navigator> (hoặc Tab, Drawer) phải là <Stack.Screen>**, không được là component khác, Fragment, hay text node lẻ.
Code gây lỗi (Thường gặp do indentation/khoảng trắng)
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { Button, View, Alert, Text } from 'react-native';
const Stack = createStackNavigator();
const HomePage = ({ navigation }) => (
Nguyên nhân chi tiết
| Vấn đề | Giải thích |
|---|---|
Khoảng trắng/dòng mới giữa <Stack.Screen> |
JSX coi khoảng trắng là text node -> thành child của Navigator. |
| Comment JSX giữa các Screen | {/* comment */} cũng là child. |
Bọc Screen trong <View> hoặc <> (Fragment) |
Navigator chỉ chấp nhận Screen trực tiếp. |
| Render điều kiện trực tiếp trong Navigator | {condition && <Stack.Screen ... />} sai. Phải điều kiện ở component prop hoặc dùng options.enabled. |
Code đã sửa (Đúng chuẩn)
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { Button, View, Alert, Text } from 'react-native';
const Stack = createStackNavigator();
const HomePage = ({ navigation }) => (
Cách render điều kiện Screen (Đúng)
Cách 1: Điều kiện trong component prop
Cách 2: Dùng
options.enabled(React Navigation 6+)Cách 3: Dynamic routes (Khuyên dùng cho phức tạp)
const MyStack = () => { const routes = isLoggedIn ? [ { name: 'Home', component: HomeScreen }, { name: 'Profile', component: ProfileScreen }, ] : [ { name: 'Login', component: LoginScreen }, ]; return ({routes.map(route => ( ); };))} ESLint Rule phòng ngừa
Cài
eslint-plugin-react-nativevà bật rule:"react-native/no-raw-text": "error"Sẽ báo lỗi ngay khi có text node lẻ trong JSX.
Tóm tắt
- Con trực tiếp của Navigator = chỉ
<Stack.Screen>/<Tab.Screen>/<Drawer.Screen>.- Không có khoảng trắng, comment, Fragment, View, Text... giữa chúng.
- Render điều kiện: map mảng routes hoặc điều kiện ở prop
component/options.enabled.