React Native中useEffect触发元素类型无效错误排查求助
问题描述
加载代码时触发如下错误:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of "Page".
代码如下:
import {Stack, useRouter} from "expo-router"; import {Card, Menu, Text} from "@ui-kitten/components"; import {AuthService} from "../services/AuthService"; import {useEffect, useState} from "react"; export default function Page() { const router = useRouter(); const [auth, setAuth] = useState(null); const [companies, setCompanies] = useState([]); const [activeCompany, setActiveCompany] = useState(null); useEffect(() => { AuthService.getAuth().then(tempAuth => { setAuth(tempAuth); if (tempAuth !== null) { setCompanies(tempAuth.companies) AuthService.getActiveCompany().then(activeCompany => { console.log(activeCompany, 'active company') setActiveCompany(activeCompany); } ) } }) }, []) return ( <> <Stack.Screen options={{ title: activeCompany === null ? 'Choose company' : activeCompany.name, headerBackVisible: false }}/> </> ) }
控制台打印显示company变量不为空,尝试硬编码setActiveCompany({id: 'test'});仍出现相同错误,请问哪里操作有误?
问题原因与解决方法
错误根源
你在页面组件的return中直接渲染Stack.Screen,这违反了expo-router的使用规则。Stack.Screen是用于在路由布局文件(如_layout.js)中定义路由栈配置的元素,不能作为页面组件的可渲染内容直接返回,这才是导致"组件类型无效"错误的核心原因,和useEffect里的状态更新逻辑无关。
解决步骤
- 移除页面中的
Stack.Screen:页面组件的return必须返回实际可渲染的UI元素(比如文本、容器、卡片等),不能仅保留Stack.Screen。 - 动态设置Header选项:如果需要根据
activeCompany动态修改页面标题等Header配置,使用useLayoutEffect结合router.setParams实现。
修改后的代码示例:
import {Stack, useRouter, useLayoutEffect} from "expo-router"; import {Card, Menu, Text, View} from "@ui-kitten/components"; import {AuthService} from "../services/AuthService"; import {useEffect, useState} from "react"; export default function Page() { const router = useRouter(); const [auth, setAuth] = useState(null); const [companies, setCompanies] = useState([]); const [activeCompany, setActiveCompany] = useState(null); useEffect(() => { AuthService.getAuth().then(tempAuth => { setAuth(tempAuth); if (tempAuth !== null) { setCompanies(tempAuth.companies) AuthService.getActiveCompany().then(activeCompany => { console.log(activeCompany, 'active company') setActiveCompany(activeCompany); } ) } }) }, []) // 动态设置Header参数 useLayoutEffect(() => { router.setParams({ title: activeCompany === null ? 'Choose company' : activeCompany.name, headerBackVisible: false }); }, [activeCompany]); return ( {/* 这里放页面实际需要展示的UI内容 */} <View style={{flex: 1, padding: 16}}> <Text>{activeCompany ? `当前公司:${activeCompany.name}` : '请选择公司'}</Text> {/* 可以添加公司选择的UI组件,比如列表、菜单等 */} </View> ) }
补充说明
确保你的路由布局文件(如app/_layout.js)已经正确配置了Stack容器,示例如下:
import { Stack } from 'expo-router'; export default function RootLayout() { return ( <Stack> {/* 这里定义各个路由的默认配置 */} <Stack.Screen name="index" options={{ title: '首页' }} /> <Stack.Screen name="page" /> {/* 你的Page页面路由 */} </Stack> ); }
内容的提问来源于stack exchange,提问作者Mikkel
相关产品推荐
相关产品推荐

