Expo Router中使用router.push()传递参数失败求助
Expo Router中router.push()传递参数失败,query/params为undefined
问题详情
我是React Native入门开发者,学习使用Expo Router的router.push()在页面间传递参数时遇到问题:调用router.push()传入query参数后,目标页面通过useRouter()获取的query为undefined,报错“Cannot read property 'name' of undefined”,改用params结果一样。试了官方文档、网络搜索和AI工具的方法都没解决。
项目结构
-app -_layout.jsx -index.jsx -user.jsx -components -CustomButton.jsx
现有代码
_layout.jsx
import '../global.css' // Inserts the global css file for tailwind import { Stack } from 'expo-router' const App = () => { return ( <Stack> <Stack.Screen name='index' /> <Stack.Screen name='user' /> </Stack> ) } export default App
CustomButton.jsx
import { View, Text, TouchableOpacity } from 'react-native' import React from 'react' const CustomButton = ({ title, styles, onPress }) => { return ( <TouchableOpacity className={`border p-2 mt-1 ${styles}`} onPress={onPress} > <View> <Text className='text-[20px] text-center'>{title}</Text> </View> </TouchableOpacity> ) } export default CustomButton
index.jsx
import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context' import { StatusBar } from 'expo-status-bar' import { View, Text } from 'react-native' import React from 'react' import { useRouter } from 'expo-router' import CustomButton from '../components/CustomButton' const Home = () => { const router = useRouter() return ( <SafeAreaProvider> <SafeAreaView className='flex-1 items-center justify-center p-4'> <Text className='text-5xl font-bold'>Home Page</Text> <CustomButton title={'User'} styles={'w-full bg-blue-300 rounded-[2vw]'} onPress={() => router.push({ pathname: '/user', query: { name: 'Vincent', }, }) } /> <StatusBar style='dark' /> </SafeAreaView> </SafeAreaProvider> ) } export default Home
user.jsx
import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context' import { StatusBar } from 'expo-status-bar' import { View, Text } from 'react-native' import React from 'react' import { useRouter } from 'expo-router' import CustomButton from '../components/CustomButton' const User = () => { const { query } = useRouter() console.log(query) return ( <SafeAreaProvider> <SafeAreaView className='flex-1 items-center justify-center'> <Text className='text-5xl font-bold'>User Page</Text> <Text className='text-3xl font-bold'> Welcome, {query.name} </Text> <StatusBar style='dark' /> </SafeAreaView> </SafeAreaProvider> ) } export default User
依赖版本
{ "name": "react-native-tutorial", "version": "1.0.0", "main": "expo-router/entry", "scripts": { "start": "expo start", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web" }, "dependencies": { "expo": "~52.0.28", "expo-constants": "~17.0.5", "expo-linking": "~7.0.5", "expo-router": "~4.0.17", "expo-status-bar": "~2.0.1", "nativewind": "^4.1.23", "react": "18.3.1", "react-native": "0.76.6", "react-native-reanimated": "^3.16.7", "react-native-safe-area-context": "^4.12.0", "react-native-screens": "~4.4.0", "tailwindcss": "^3.4.17" }, "devDependencies": { "@babel/core": "^7.20.0" }, "private": true }
解决方法
核心问题:参数获取方式错误
Expo Router v4版本中,useRouter()不再直接暴露query或params对象,需要使用专门的useLocalSearchParams()钩子来获取路由传递的query参数。
修改user.jsx代码
将原来的参数获取逻辑替换为useLocalSearchParams():
import { SafeAreaView } from 'react-native-safe-area-context' import { StatusBar } from 'expo-status-bar' import { View, Text } from 'react-native' import React from 'react' import { useLocalSearchParams } from 'expo-router' const User = () => { const query = useLocalSearchParams() console.log(query) return ( <SafeAreaView className='flex-1 items-center justify-center'> <Text className='text-5xl font-bold'>User Page</Text> {/* 增加默认值避免参数不存在时报错 */} <Text className='text-3xl font-bold'> Welcome, {query.name || 'Guest'} </Text> <StatusBar style='dark' /> </SafeAreaView> ) } export default User
额外优化:避免重复渲染SafeAreaProvider
不要在每个页面都包裹SafeAreaProvider,将其移到根布局_layout.jsx中,减少嵌套和不必要的组件渲染:
优化后的_layout.jsx
import '../global.css' import { Stack } from 'expo-router' import { SafeAreaProvider } from 'react-native-safe-area-context' const App = () => { return ( <SafeAreaProvider> <Stack> <Stack.Screen name='index' /> <Stack.Screen name='user' /> </Stack> </SafeAreaProvider> ) } export default App
优化后的index.jsx(移除内部的SafeAreaProvider)
import { SafeAreaView } from 'react-native-safe-area-context' import { StatusBar } from 'expo-status-bar' import { View, Text } from 'react-native' import React from 'react' import { useRouter } from 'expo-router' import CustomButton from '../components/CustomButton' const Home = () => { const router = useRouter() return ( <SafeAreaView className='flex-1 items-center justify-center p-4'> <Text className='text-5xl font-bold'>Home Page</Text> <CustomButton title={'User'} styles={'w-full bg-blue-300 rounded-[2vw]'} onPress={() => router.push({ pathname: '/user', query: { name: 'Vincent', }, }) } /> <StatusBar style='dark' /> </SafeAreaView> ) } export default Home
内容的提问来源于stack exchange,提问作者Vince
相关产品推荐
相关产品推荐

