React Navigation深度链接与启动屏useEffect冲突致双重导航问题求助
问题背景
我在处理应用的深度链接逻辑,使用react-navigation的深度链接功能处理传入的URL请求,但启动屏中的useEffect会在应用状态加载完成后自动重定向用户,导致双重重定向的异常问题。
启动屏useEffect代码
useEffect(() => { if (isAppReadyToRedirect) { if (!user) { // 未登录状态 resetToRootScreen(RootScreen.Auth); // 基于navigationRef封装的路由重置方法 } else if (user.isAnonymous) { // 匿名用户状态 redirectAnonymousUser(); } else { // 已绑定邮箱的登录用户 resetToRootScreen(RootScreen.HomeTabs); } } }, [isAppReadyToRedirect, user]);
深度链接配置代码
export const linkingConfig = { prefixes: [DEEP_LINK_SCHEME], subscribe(listener: any) { const branchUnsubscribe = branch.subscribe(({ error, params }) => { if (error) { logError(error); return; } if (params) { const url = params.$canonical_url; if (url) { listener(url); } } }); return () => { branchUnsubscribe(); }; }, config: { screens: { // 路由映射配置 }, }, };
解决方案
可以通过以下几种方式判断深度链接是否已触发重定向,从而阻止启动屏的默认重定向逻辑:
方法1:标记深度链接处理状态
通过全局状态(Context/Redux/全局变量)标记深度链接是否已处理,在启动屏的useEffect中跳过默认重定向。
步骤1:创建深度链接状态Context
import { createContext, useContext, useState } from 'react'; const DeepLinkContext = createContext(); export function DeepLinkProvider({ children }) { const [isDeepLinkHandled, setIsDeepLinkHandled] = useState(false); return ( <DeepLinkContext.Provider value={{ isDeepLinkHandled, setIsDeepLinkHandled }}> {children} </DeepLinkContext.Provider> ); } export function useDeepLink() { return useContext(DeepLinkContext); }
步骤2:在深度链接订阅中标记状态
// 若linkingConfig在组件外部定义,可改用全局变量或Redux管理状态 export const linkingConfig = { prefixes: [DEEP_LINK_SCHEME], subscribe(listener: any) { // 这里需通过全局变量或状态管理库访问setIsDeepLinkHandled const branchUnsubscribe = branch.subscribe(({ error, params }) => { if (error) { logError(error); return; } if (params) { const url = params.$canonical_url; if (url) { listener(url); // 标记深度链接已处理 setIsDeepLinkHandled(true); } } }); return () => { branchUnsubscribe(); }; }, config: { screens: { // 路由映射配置 }, }, };
步骤3:在启动屏useEffect中判断状态
import { useDeepLink } from './DeepLinkContext'; // ... const { isDeepLinkHandled } = useDeepLink(); useEffect(() => { // 仅当深度链接未处理时,执行默认重定向 if (isAppReadyToRedirect && !isDeepLinkHandled) { if (!user) { resetToRootScreen(RootScreen.Auth); } else if (user.isAnonymous) { redirectAnonymousUser(); } else { resetToRootScreen(RootScreen.HomeTabs); } } }, [isAppReadyToRedirect, user, isDeepLinkHandled]);
方法2:通过导航栈状态判断
利用navigationRef获取当前导航栈状态,判断是否已被深度链接修改,若已有非启动屏的路由,则跳过默认重定向。
import { navigationRef } from './navigation'; useEffect(() => { if (isAppReadyToRedirect) { const currentState = navigationRef.getState(); // 检查导航栈是否已有非启动屏的路由 const hasDeepLinkNavigation = currentState.routes.length > 1 || currentState.routes[0].name !== 'SplashScreen'; if (!hasDeepLinkNavigation) { if (!user) { resetToRootScreen(RootScreen.Auth); } else if (user.isAnonymous) { redirectAnonymousUser(); } else { resetToRootScreen(RootScreen.HomeTabs); } } } }, [isAppReadyToRedirect, user]);
方法3:检查初始深度链接URL
在App初始化时获取初始深度链接URL,传递给启动屏,以此判断是否需要执行默认重定向。
步骤1:在App组件中获取初始URL
import { Linking } from 'react-native'; function App() { const [initialDeepLinkUrl, setInitialDeepLinkUrl] = useState(null); useEffect(() => { Linking.getInitialURL().then(url => { if (url) { setInitialDeepLinkUrl(url); } }); }, []); return ( <NavigationContainer linking={linkingConfig} ref={navigationRef}> <SplashScreen initialDeepLinkUrl={initialDeepLinkUrl} /> </NavigationContainer> ); }
步骤2:在启动屏useEffect中判断
function SplashScreen({ initialDeepLinkUrl }) { // ... useEffect(() => { // 没有初始深度链接时才执行默认重定向 if (isAppReadyToRedirect && !initialDeepLinkUrl) { if (!user) { resetToRootScreen(RootScreen.Auth); } else if (user.isAnonymous) { redirectAnonymousUser(); } else { resetToRootScreen(RootScreen.HomeTabs); } } }, [isAppReadyToRedirect, user, initialDeepLinkUrl]); // ... }
内容的提问来源于stack exchange,提问作者therealcobb
相关产品推荐
相关产品推荐

