React Navigation 6及以上版本如何从组件向导航器头部传递props?
方案一:Props 传递(简单场景)
适合通知状态仅在初始化时获取、后续无需更新的场景。
- 在App组件中维护未读计数状态
修正原代码异步逻辑的问题,将未读计数存入状态并传递给导航组件:
const App = () => { const [notifications, setNotifications] = useState([]); const [unreadCount, setUnreadCount] = useState(0); useEffect(() => { const fetchNotifications = async () => { const fetchedNotifications = await API.fetch(); setNotifications(fetchedNotifications); // 计算未读数量 const count = fetchedNotifications.filter(n => !n.isRead).length; setUnreadCount(count); }; fetchNotifications(); }, []); return ( <NavigationContainer> <MyStack unreadCount={unreadCount} /> </NavigationContainer> ); }
- 将计数传递到Tab导航组件
修改MyStack,把unreadCount传递给MyTabs:
const MyStack = ({ unreadCount }) => { const navigation = useNavigation(); return ( <Stack.Navigator> <Stack.Group> <Stack.Screen name="Tabs" options={{ headerShown: false }}> {(props) => <MyTabs {...props} unreadCount={unreadCount} />} </Stack.Screen> {/* 原有Notifications屏幕代码不变 */} </Stack.Group> </Stack.Navigator> ); }
- 在Tab导航头部显示计数
修改MyTabs的headerRight,添加未读计数标记:
const MyTabs = ({ unreadCount }) => { const navigation = useNavigation(); return ( <Tab.Navigator screenOptions={{ headerRight: () => ( <TouchableOpacity onPress={() => navigation.navigate("Notifications")} style={{ position: 'relative', marginRight: 16 }} > <Ionicons name="notifications" size={24} color="black"/> {/* 仅当有未读时显示计数 */} {unreadCount > 0 && ( <View style={{ position: 'absolute', top: -4, right: -4, backgroundColor: '#ff3b30', borderRadius: 10, width: 20, height: 20, justifyContent: 'center', alignItems: 'center' }}> <Text style={{ color: 'white', fontSize: 12, fontWeight: 'bold' }}> {unreadCount} </Text> </View> )} </TouchableOpacity> )} }} > {/* 你的Tab屏幕组件 */} </Tab.Navigator> ); }
方案二:React Context 管理(复杂场景)
适合需要在多个组件中更新通知状态(比如在通知列表标记已读)的场景,避免层层传递props。
- 创建通知状态上下文
import { createContext, useContext, useState, useEffect } from 'react'; const NotificationContext = createContext(); export const NotificationProvider = ({ children }) => { const [notifications, setNotifications] = useState([]); const [unreadCount, setUnreadCount] = useState(0); // 初始化获取通知 useEffect(() => { const fetchNotifications = async () => { const fetchedNotifications = await API.fetch(); setNotifications(fetchedNotifications); updateUnreadCount(fetchedNotifications); }; fetchNotifications(); }, []); // 更新未读计数的工具函数 const updateUnreadCount = (notifs) => { const count = notifs.filter(n => !n.isRead).length; setUnreadCount(count); }; // 标记单条通知为已读 const markNotificationAsRead = (notificationId) => { const updatedNotifs = notifications.map(n => n.id === notificationId ? { ...n, isRead: true } : n ); setNotifications(updatedNotifs); updateUnreadCount(updatedNotifs); // 这里可添加调用API更新后端状态的逻辑 }; return ( <NotificationContext.Provider value={{ notifications, unreadCount, markNotificationAsRead }} > {children} </NotificationContext.Provider> ); }; // 自定义Hook简化上下文调用 export const useNotifications = () => useContext(NotificationContext);
- 在App中包裹导航容器
const App = () => { return ( <NotificationProvider> <NavigationContainer> <MyStack /> </NavigationContainer> </NotificationProvider> ); }
- 在Tab导航头部获取计数
const MyTabs = () => { const navigation = useNavigation(); const { unreadCount } = useNotifications(); // 直接从上下文获取计数 return ( <Tab.Navigator screenOptions={{ headerRight: () => ( <TouchableOpacity onPress={() => navigation.navigate("Notifications")} style={{ position: 'relative', marginRight: 16 }} > <Ionicons name="notifications" size={24} color="black"/> {unreadCount > 0 && ( <View style={{ position: 'absolute', top: -4, right: -4, backgroundColor: '#ff3b30', borderRadius: 10, width: 20, height: 20, justifyContent: 'center', alignItems: 'center' }}> <Text style={{ color: 'white', fontSize: 12, fontWeight: 'bold' }}> {unreadCount} </Text> </View> )} </TouchableOpacity> )} }} > {/* 你的Tab屏幕组件 */} </Tab.Navigator> ); }
- 在通知列表中更新状态
const NotificationsScreen = () => { const { notifications, markNotificationAsRead } = useNotifications(); return ( <View style={{ padding: 16 }}> {notifications.map(notification => ( <TouchableOpacity key={notification.id} onPress={() => markNotificationAsRead(notification.id)} style={{ paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#eee' }} > <Text style={{ fontWeight: notification.isRead ? 'normal' : 'bold', fontSize: 16 }}> {notification.title} </Text> <Text style={{ color: '#666', marginTop: 4 }}> {notification.content} </Text> </TouchableOpacity> ))} </View> ); }
内容的提问来源于stack exchange,提问作者user6377312
相关产品推荐
相关产品推荐

