refactor(navigation): replace direct navigation with navigation service
Replace direct `navigation.navigate()` and `navigation.getParent()?.navigate()` calls with centralized `navigationService.navigate()` across multiple screens. Convert screen component functions from JSX elements to array-returning functions in RootNavigator to fix React key warnings and improve render consistency. - HomeScreen: use navigationService for post and user navigation - PrivateChatInfoScreen: use navigationService for profile navigation - ChatScreen: use navigationService for avatar press and user profile navigation - RootNavigator: convert PublicScreens and AuthenticatedScreens to getPublicScreens() and getAuthenticatedScreens() functions returning arrays with proper keys
This commit is contained in:
@@ -41,10 +41,10 @@ interface RootNavigatorProps {
|
|||||||
isInitializing: boolean;
|
isInitializing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 未认证时可访问的屏幕
|
// 未认证时可访问的屏幕 - 返回数组而不是 JSX
|
||||||
const PublicScreens = () => (
|
const getPublicScreens = () => [
|
||||||
<>
|
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="PostDetail"
|
||||||
name="PostDetail"
|
name="PostDetail"
|
||||||
component={PostDetailScreen}
|
component={PostDetailScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -54,8 +54,9 @@ const PublicScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="UserProfile"
|
||||||
name="UserProfile"
|
name="UserProfile"
|
||||||
component={UserScreen}
|
component={UserScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -64,14 +65,13 @@ const PublicScreens = () => (
|
|||||||
headerStyle: { backgroundColor: colors.background.paper },
|
headerStyle: { backgroundColor: colors.background.paper },
|
||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
</>
|
];
|
||||||
);
|
|
||||||
|
|
||||||
// 认证后可访问的屏幕
|
// 认证后可访问的屏幕 - 返回数组而不是 JSX
|
||||||
const AuthenticatedScreens = () => (
|
const getAuthenticatedScreens = () => [
|
||||||
<>
|
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="PostDetail"
|
||||||
name="PostDetail"
|
name="PostDetail"
|
||||||
component={PostDetailScreen}
|
component={PostDetailScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -81,8 +81,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="UserProfile"
|
||||||
name="UserProfile"
|
name="UserProfile"
|
||||||
component={UserScreen}
|
component={UserScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -91,8 +92,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerStyle: { backgroundColor: colors.background.paper },
|
headerStyle: { backgroundColor: colors.background.paper },
|
||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="CreatePost"
|
||||||
name="CreatePost"
|
name="CreatePost"
|
||||||
component={CreatePostScreen}
|
component={CreatePostScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -102,16 +104,18 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
presentation: 'modal',
|
presentation: 'modal',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="Chat"
|
||||||
name="Chat"
|
name="Chat"
|
||||||
component={ChatScreen}
|
component={ChatScreen}
|
||||||
options={{
|
options={{
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="FollowList"
|
||||||
name="FollowList"
|
name="FollowList"
|
||||||
component={FollowListScreen}
|
component={FollowListScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -121,8 +125,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="CreateGroup"
|
||||||
name="CreateGroup"
|
name="CreateGroup"
|
||||||
component={CreateGroupScreen}
|
component={CreateGroupScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -132,8 +137,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
presentation: 'modal',
|
presentation: 'modal',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="JoinGroup"
|
||||||
name="JoinGroup"
|
name="JoinGroup"
|
||||||
component={JoinGroupScreen}
|
component={JoinGroupScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -143,8 +149,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="GroupInfo"
|
||||||
name="GroupInfo"
|
name="GroupInfo"
|
||||||
component={GroupInfoScreen}
|
component={GroupInfoScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -154,8 +161,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="GroupMembers"
|
||||||
name="GroupMembers"
|
name="GroupMembers"
|
||||||
component={GroupMembersScreen}
|
component={GroupMembersScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -165,8 +173,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="GroupRequestDetail"
|
||||||
name="GroupRequestDetail"
|
name="GroupRequestDetail"
|
||||||
component={GroupRequestDetailScreen}
|
component={GroupRequestDetailScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -176,8 +185,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="GroupInviteDetail"
|
||||||
name="GroupInviteDetail"
|
name="GroupInviteDetail"
|
||||||
component={GroupInviteDetailScreen}
|
component={GroupInviteDetailScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -187,8 +197,9 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<RootStack.Screen
|
<RootStack.Screen
|
||||||
|
key="PrivateChatInfo"
|
||||||
name="PrivateChatInfo"
|
name="PrivateChatInfo"
|
||||||
component={PrivateChatInfoScreen}
|
component={PrivateChatInfoScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -198,9 +209,8 @@ const AuthenticatedScreens = () => (
|
|||||||
headerTintColor: colors.text.primary,
|
headerTintColor: colors.text.primary,
|
||||||
animation: 'slide_from_right',
|
animation: 'slide_from_right',
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
</>
|
];
|
||||||
);
|
|
||||||
|
|
||||||
export function RootNavigator({ isAuthenticated, isInitializing }: RootNavigatorProps) {
|
export function RootNavigator({ isAuthenticated, isInitializing }: RootNavigatorProps) {
|
||||||
const { isMobile } = useResponsive();
|
const { isMobile } = useResponsive();
|
||||||
@@ -238,7 +248,7 @@ export function RootNavigator({ isAuthenticated, isInitializing }: RootNavigator
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
</RootStack.Screen>
|
</RootStack.Screen>
|
||||||
<AuthenticatedScreens />
|
{getAuthenticatedScreens()}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -247,7 +257,7 @@ export function RootNavigator({ isAuthenticated, isInitializing }: RootNavigator
|
|||||||
component={AuthNavigator}
|
component={AuthNavigator}
|
||||||
options={{ headerShown: false }}
|
options={{ headerShown: false }}
|
||||||
/>
|
/>
|
||||||
<PublicScreens />
|
{getPublicScreens()}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</RootStack.Navigator>
|
</RootStack.Navigator>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import { HomeStackParamList, RootStackParamList } from '../../navigation/types';
|
|||||||
import { useResponsive, useResponsiveSpacing } from '../../hooks/useResponsive';
|
import { useResponsive, useResponsiveSpacing } from '../../hooks/useResponsive';
|
||||||
import { SearchScreen } from './SearchScreen';
|
import { SearchScreen } from './SearchScreen';
|
||||||
import { CreatePostScreen } from '../create/CreatePostScreen';
|
import { CreatePostScreen } from '../create/CreatePostScreen';
|
||||||
|
import { navigationService } from '../../infrastructure/navigation/navigationService';
|
||||||
|
|
||||||
type NavigationProp = NativeStackNavigationProp<HomeStackParamList, 'Home'> & NativeStackNavigationProp<RootStackParamList>;
|
type NavigationProp = NativeStackNavigationProp<HomeStackParamList, 'Home'> & NativeStackNavigationProp<RootStackParamList>;
|
||||||
|
|
||||||
@@ -343,12 +344,12 @@ export const HomeScreen: React.FC = () => {
|
|||||||
|
|
||||||
// 跳转到帖子详情
|
// 跳转到帖子详情
|
||||||
const handlePostPress = (postId: string, scrollToComments: boolean = false) => {
|
const handlePostPress = (postId: string, scrollToComments: boolean = false) => {
|
||||||
navigation.getParent()?.navigate('PostDetail', { postId, scrollToComments });
|
navigationService.navigate('PostDetail', { postId, scrollToComments });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转到用户主页
|
// 跳转到用户主页
|
||||||
const handleUserPress = (userId: string) => {
|
const handleUserPress = (userId: string) => {
|
||||||
navigation.getParent()?.navigate('UserProfile', { userId });
|
navigationService.navigate('UserProfile', { userId });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 点赞帖子
|
// 点赞帖子
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { userManager } from '../../stores/userManager';
|
|||||||
import { Avatar, Text, Button, Loading, Divider } from '../../components/common';
|
import { Avatar, Text, Button, Loading, Divider } from '../../components/common';
|
||||||
import { User } from '../../types';
|
import { User } from '../../types';
|
||||||
import { RootStackParamList, MessageStackParamList } from '../../navigation/types';
|
import { RootStackParamList, MessageStackParamList } from '../../navigation/types';
|
||||||
|
import { navigationService } from '../../infrastructure/navigation/navigationService';
|
||||||
|
|
||||||
type NavigationProp = NativeStackNavigationProp<MessageStackParamList>;
|
type NavigationProp = NativeStackNavigationProp<MessageStackParamList>;
|
||||||
type PrivateChatInfoRouteProp = RouteProp<MessageStackParamList, 'PrivateChatInfo'>;
|
type PrivateChatInfoRouteProp = RouteProp<MessageStackParamList, 'PrivateChatInfo'>;
|
||||||
@@ -149,9 +150,8 @@ const PrivateChatInfoScreen: React.FC = () => {
|
|||||||
|
|
||||||
// 查看用户资料
|
// 查看用户资料
|
||||||
const handleViewProfile = () => {
|
const handleViewProfile = () => {
|
||||||
// 使用根导航跳转到用户资料页面
|
// 使用导航服务跳转到用户资料页面
|
||||||
const rootNavigation = navigation.getParent();
|
navigationService.navigate('UserProfile', { userId });
|
||||||
rootNavigation?.navigate('UserProfile' as any, { userId });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 举报/投诉
|
// 举报/投诉
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { groupService } from '../../../../services/groupService';
|
|||||||
import { userManager } from '../../../../stores/userManager';
|
import { userManager } from '../../../../stores/userManager';
|
||||||
import { groupManager } from '../../../../stores/groupManager';
|
import { groupManager } from '../../../../stores/groupManager';
|
||||||
import { RootStackParamList } from '../../../../navigation/types';
|
import { RootStackParamList } from '../../../../navigation/types';
|
||||||
|
import { navigationService } from '../../../../infrastructure/navigation/navigationService';
|
||||||
import {
|
import {
|
||||||
GroupMessage,
|
GroupMessage,
|
||||||
PanelType,
|
PanelType,
|
||||||
@@ -1039,9 +1040,9 @@ export const useChatScreen = () => {
|
|||||||
// 点击头像跳转到用户主页
|
// 点击头像跳转到用户主页
|
||||||
const handleAvatarPress = useCallback((userId: string) => {
|
const handleAvatarPress = useCallback((userId: string) => {
|
||||||
if (userId && userId !== currentUserId) {
|
if (userId && userId !== currentUserId) {
|
||||||
navigation.navigate('UserProfile' as any, { userId: String(userId) });
|
navigationService.navigate('UserProfile', { userId: String(userId) });
|
||||||
}
|
}
|
||||||
}, [navigation, currentUserId]);
|
}, [currentUserId]);
|
||||||
|
|
||||||
// 长按头像@用户
|
// 长按头像@用户
|
||||||
const handleAvatarLongPress = useCallback((senderId: string, nickname: string) => {
|
const handleAvatarLongPress = useCallback((senderId: string, nickname: string) => {
|
||||||
@@ -1113,8 +1114,7 @@ export const useChatScreen = () => {
|
|||||||
conversationId: conversationId || undefined,
|
conversationId: conversationId || undefined,
|
||||||
});
|
});
|
||||||
} else if (otherUser?.id) {
|
} else if (otherUser?.id) {
|
||||||
const rootNavigation = navigation.getParent();
|
navigationService.navigate('UserProfile', { userId: String(otherUser.id) });
|
||||||
rootNavigation?.navigate('UserProfile' as any, { userId: String(otherUser.id) });
|
|
||||||
}
|
}
|
||||||
}, [navigation, isGroupChat, routeGroupId, otherUser]);
|
}, [navigation, isGroupChat, routeGroupId, otherUser]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user