React Native中不同屏幕间传递数据的正确方式是什么?
问题描述
我目前通过React Navigation的参数在两个屏幕间传递对象,代码能正常运行:
第一个屏幕代码
export const FirstScreen = ({ navigation }) => { const object = { name: "John", surname: "Smith" }; return ( <View> <Button onPress={() => navigation.navigate("MainStack", { screen: "SecondScreen", params: { object: object }, }) } /> </View> ); };
第二个屏幕代码
export const SecondScreen = ({ route }) => { const [object, setObject] = useState({}); useEffect(() => { if (route.params?.object) setObject(route.params?.object); }, []); return ( <View> <Text> {object.name} </Text> <Text> {object.surname} </Text> </View> ); };
不过根据React Navigation文档的说法,这种做法属于反模式,核心原因是没必要重复传递完整数据:
要明确参数里应该放什么数据。参数就像屏幕的配置选项,只应该包含用来配置屏幕显示的信息。别直接传屏幕要展示的完整数据(比如传用户ID而非用户对象)。另外,多个屏幕都会用到的数据也不该放在参数里,这类数据应该存到全局状态中。
我知道应该改用全局状态+导航参数定位数据的模式,Redux感觉大材小用,React Context看起来更适配,但有没有更优的、被业界认可的最佳实践方案?
最佳实践方案
针对这类场景,除了React Context,还有几种更贴合React生态的常用方案,都是行业内公认的最佳实践:
1. React Query/SWR(推荐用于后端数据场景)
如果你的数据是从后端获取的,用React Query或SWR这类数据请求库是最优解。它们自带缓存、数据同步能力,本质上是把数据存在全局缓存中:
- 导航时只传数据的唯一标识(比如用户ID)
- 目标屏幕通过这个标识从缓存/后端拉取完整数据
- 优势:自动处理缓存过期、后台同步,不用手动维护全局状态,代码更简洁
示例代码:
// 第一个屏幕 export const FirstScreen = ({ navigation }) => { const userId = "123"; // 数据的唯一标识 return ( <View> <Button onPress={() => navigation.navigate("MainStack", { screen: "SecondScreen", params: { userId }, }) } /> </View> ); }; // 第二个屏幕 export const SecondScreen = ({ route }) => { const { userId } = route.params; // 用useQuery从缓存/后端获取数据 const { data: user } = useQuery(["user", userId], () => fetchUserById(userId)); if (!user) return <Text>加载中...</Text>; return ( <View> <Text>{user.name}</Text> <Text>{user.surname}</Text> </View> ); };
2. Zustand/Jotai(推荐用于前端本地数据场景)
如果数据是前端生成、不需要和后端同步的,Zustand或Jotai这类轻量状态库比Redux轻便太多,也比Context更易用:
- 定义一个全局状态存储所有数据
- 导航时传唯一标识,目标屏幕从状态中根据标识提取对应数据
- 优势:API极简,不需要像Context那样套多层Provider,性能表现也更好
示例(Zustand):
// store.js import { create } from 'zustand'; export const useUserStore = create((set) => ({ users: { "123": { name: "John", surname: "Smith" } }, addUser: (user) => set((state) => ({ users: {...state.users, [user.id]: user } })) })); // 第一个屏幕 export const FirstScreen = ({ navigation }) => { const userId = "123"; return ( <View> <Button onPress={() => navigation.navigate("MainStack", { screen: "SecondScreen", params: { userId }, }) } /> </View> ); }; // 第二个屏幕 export const SecondScreen = ({ route }) => { const { userId } = route.params; const user = useUserStore(state => state.users[userId]); return ( <View> <Text>{user.name}</Text> <Text>{user.surname}</Text> </View> ); };
3. 继续使用React Context(适合简单场景)
如果你的项目已经在使用Context,或者业务场景非常简单,继续用Context完全没问题,只需注意不要把Context拆得太细导致多层嵌套即可。
总结
- 数据来自后端:优先选React Query/SWR,自带缓存和同步,减少状态维护成本
- 前端本地数据:选Zustand/Jotai,比Context更轻便
- 极小项目/已有Context依赖:继续用Context也完全可行
内容的提问来源于stack exchange,提问作者Baski
相关产品推荐
相关产品推荐

