React Native中使用useContext在多页面/视图间共享偏好参数的技术问题
React Native中使用useContext在多页面/视图间共享偏好参数的技术问题
兄弟,我太懂你这种刚上手React Native,想跨页面共享状态的头疼了!你的场景刚好是Context API的典型用例——不用层层传递props,就能在任何页面轻松拿到和修改那个选中的偏好字段ID,我给你一步步说怎么实现:
第一步:创建全局的偏好状态Context
首先咱新建一个专门的Context文件,比如src/contexts/PreferenceContext.tsx,把状态和修改方法封装在这里,这样所有页面都能复用:
import React, { createContext, useContext, useState, ReactNode } from 'react'; // 定义Context的类型,让TS帮我们做类型检查 type PreferenceContextType = { selectedFieldId: string | null; setSelectedFieldId: (id: string | null) => void; }; // 创建Context,默认值设为undefined,后面会用Provider覆盖 const PreferenceContext = createContext<PreferenceContextType | undefined>(undefined); // 定义Provider组件,所有需要访问状态的子组件都要被它包裹 export const PreferenceProvider = ({ children }: { children: ReactNode }) => { // 初始化选中的字段ID,默认是null(还没选的状态) const [selectedFieldId, setSelectedFieldId] = useState<string | null>(null); return ( <PreferenceContext.Provider value={{ selectedFieldId, setSelectedFieldId }}> {children} </PreferenceContext.Provider> ); }; // 自定义Hook,简化Context的使用,还能做边界检查 export const usePreference = () => { const context = useContext(PreferenceContext); if (!context) { throw new Error('usePreference必须在PreferenceProvider的子组件中使用哦'); } return context; };
第二步:在根组件中包裹Provider
接下来要把这个Provider套在你的App最外层,比如App.tsx里,这样所有页面都能访问到Context里的状态:
import { PreferenceProvider } from './src/contexts/PreferenceContext'; import { NavigationContainer } from '@react-navigation/native'; // 导入你的路由组件 import AppNavigator from './src/navigation/AppNavigator'; export default function App() { return ( <PreferenceProvider> <NavigationContainer> <AppNavigator /> </NavigationContainer> </PreferenceProvider> ); }
第三步:在Setting页面修改偏好状态
现在到setting.tsx里,用我们自定义的usePreferenceHook拿到修改状态的方法,在用户选择字段的时候更新:
import React from 'react'; import { View, Picker, StyleSheet } from 'react-native'; import { usePreference } from '../contexts/PreferenceContext'; const SettingScreen = () => { const { selectedFieldId, setSelectedFieldId } = usePreference(); // 假设你的字段列表是这个,你可以换成自己的实际数据 const fields = [ { id: 'field_temp', name: '温度' }, { id: 'field_humid', name: '湿度' }, { id: 'field_press', name: '气压' }, ]; return ( <View style={styles.container}> <Picker selectedValue={selectedFieldId} // 回显当前选中的字段 onValueChange={(itemValue) => setSelectedFieldId(itemValue)} style={styles.picker} > {fields.map(field => ( <Picker.Item key={field.id} label={field.name} value={field.id} /> ))} </Picker> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center', }, picker: { height: 50, width: '100%', }, }); export default SettingScreen;
第四步:在Stations页面读取并使用偏好状态
最后到stations.tsx里,同样用usePreferenceHook拿到选中的字段ID,直接显示或者在请求里用:
import React, { useEffect, useState } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import { usePreference } from '../contexts/PreferenceContext'; const StationsScreen = () => { const { selectedFieldId } = usePreference(); const [stations, setStations] = useState<any[]>([]); // 模拟你的queryFetch请求,带上选中的字段ID useEffect(() => { if (selectedFieldId) { const fetchStations = async () => { // 这里替换成你自己的实际接口请求 const response = await fetch(`你的后端接口地址?fieldId=${selectedFieldId}`); const data = await response.json(); setStations(data.stations); }; fetchStations(); } }, [selectedFieldId]); // 字段ID变化时自动重新请求数据 return ( <View style={styles.container}> {selectedFieldId ? ( <Text style={styles.infoText}>当前选中的字段ID:{selectedFieldId}</Text> ) : ( <Text style={styles.infoText}>请先到设置页面选择偏好字段哦</Text> )} {/* 渲染车站数据 */} {stations.map(station => ( <Text key={station.id} style={styles.stationText}> {station.name} - 对应数据:{station.measures[selectedFieldId]} </Text> ))} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, infoText: { fontSize: 16, marginBottom: 20, }, stationText: { fontSize: 14, marginVertical: 8, }, }); export default StationsScreen;
额外补充:持久化偏好(可选)
如果希望App重启后还能保留用户的偏好,咱可以结合AsyncStorage来做持久化,修改一下Provider的代码就行:
// 在PreferenceContext.tsx里导入AsyncStorage import AsyncStorage from '@react-native-async-storage/async-storage'; export const PreferenceProvider = ({ children }: { children: ReactNode }) => { const [selectedFieldId, setSelectedFieldId] = useState<string | null>(null); // 初始化时从本地存储读取之前保存的偏好 useEffect(() => { const loadSavedPreference = async () => { const savedId = await AsyncStorage.getItem('selectedFieldId'); if (savedId) setSelectedFieldId(savedId); }; loadSavedPreference(); }, []); // 修改状态时同步存到本地存储 const updateSelectedFieldId = async (id: string | null) => { setSelectedFieldId(id); if (id) { await AsyncStorage.setItem('selectedFieldId', id); } else { await AsyncStorage.removeItem('selectedFieldId'); } }; return ( <PreferenceContext.Provider value={{ selectedFieldId, setSelectedFieldId: updateSelectedFieldId }}> {children} </PreferenceContext.Provider> ); };
这样就完美解决你的问题啦!不管你在设置页改多少次,车站页都会实时同步更新,所有页面都能轻松拿到这个偏好参数。
内容来源于stack exchange
相关产品推荐
相关产品推荐

