如何使用Expo Router在页面间传递对象(无需URL参数)
Expo Router 无需URL参数传递对象的实现方法
问题核心
你当前通过router.push的params传对象的方式,会把对象序列化为URL参数,导致URL臃肿、特殊字符转义等问题,完全没必要。下面给你两种实用的解决方案:
方法一:利用router的state传递内存态对象
这是最简单的方案,对象仅存在内存中,不会暴露在URL里,适合纯移动端场景(移动端不会主动刷新页面)。
1. 修改列表页的跳转函数
把对象放在router.push的第二个参数(state)中:
import { useRouter } from 'expo-router'; const getDetails = (item) => { const router = useRouter(); router.push( { pathname: `/details/${item.id}` }, // 仅保留必要的ID在URL(也可以直接写'/details') { state: { item } } // 完整对象存在内存态,不会出现在URL中 ); };
2. 详情页获取对象
通过router.state直接取出传递的对象:
import { useRouter } from 'expo-router'; import { Text, Image } from 'react-native'; export default function DetailsPage() { const router = useRouter(); const item = router.state?.item; // 处理用户直接访问详情页的情况 if (!item) { return <Text>暂无数据</Text>; } return ( <> <Image source={{ uri: item.imageURL }} style={{ width: 200, height: 200 }} /> <Text>{item.title}</Text> {/* 渲染其他字段 */} </> ); }
方法二:全局状态管理(适合跨页面共享/持久化场景)
如果需要在多个页面共享数据,或者担心web端刷新页面丢失数据,可以用React Context或轻量状态库(比如Zustand、Jotai)。这里以React Context为例:
1. 创建全局Context
// context/SelectedItemContext.js import { createContext, useContext, useState } from 'react'; const SelectedItemContext = createContext(); export const SelectedItemProvider = ({ children }) => { const [selectedItem, setSelectedItem] = useState(null); return ( <SelectedItemContext.Provider value={{ selectedItem, setSelectedItem }}> {children} </SelectedItemContext.Provider> ); }; export const useSelectedItem = () => useContext(SelectedItemContext);
2. 在根布局中注入Provider
// app/_layout.jsx import { SelectedItemProvider } from '../context/SelectedItemContext'; import { Stack } from 'expo-router'; export default function RootLayout() { return ( <SelectedItemProvider> <Stack /> </SelectedItemProvider> ); }
3. 列表页设置选中对象
import { useRouter } from 'expo-router'; import { useSelectedItem } from '../context/SelectedItemContext'; const getDetails = (item) => { const router = useRouter(); const { setSelectedItem } = useSelectedItem(); setSelectedItem(item); router.push(`/details/${item.id}`); };
4. 详情页获取对象
import { useSelectedItem } from '../context/SelectedItemContext'; import { Text, Image } from 'react-native'; export default function DetailsPage() { const { selectedItem } = useSelectedItem(); if (!selectedItem) { return <Text>暂无数据</Text>; } return ( <> <Image source={{ uri: selectedItem.imageURL }} style={{ width: 200, height: 200 }} /> <Text>{selectedItem.title}</Text> {/* 渲染其他字段 */} </> ); }
注意事项
- 方法一的
state在web端刷新页面后会丢失,移动端无此问题; - 如果需要持久化数据,可以在全局状态中配合
AsyncStorage存储对象; - 尽量避免在URL参数中传递复杂对象,不仅影响URL美观,还可能出现编码解码问题。
内容的提问来源于stack exchange,提问作者David Henry
相关产品推荐
相关产品推荐

