我的设置与您的类似。我按照Authentication flows · React Navigation 和SplashScreen - Expo Documentation 设置了我的身份验证流程,所以我有点失望的是,让深层链接通过它也是一个挑战。我可以通过自定义我的主开关导航器来完成这项工作,该方法类似于您所说的您现在拥有的解决方案。我只是想分享我的解决方案,所以有一个具体的例子来说明如何开始工作。我的主开关导航器是这样设置的(我也在使用 TypeScript,所以如果不熟悉类型定义,请忽略它们):
const MainNavigation = createSwitchNavigator(
{
SplashLoading,
Onboarding: OnboardingStackNavigator,
App: AppNavigator,
},
{
initialRouteName: 'SplashLoading',
}
);
const previousGetActionForPathAndParams =
MainNavigation.router.getActionForPathAndParams;
Object.assign(MainNavigation.router, {
getActionForPathAndParams(path: string, params: any) {
const isAuthLink = path.startsWith('auth-link');
if (isAuthLink) {
return NavigationActions.navigate({
routeName: 'SplashLoading',
params: { ...params, path },
});
}
return previousGetActionForPathAndParams(path, params);
},
});
export const AppNavigation = createAppContainer(MainNavigation);
您要通过身份验证流程路由的任何深层链接都需要以 auth-link 开头,或者您选择的任何前缀。这是SplashLoading 的样子:
export const SplashLoading = (props: NavigationScreenProps) => {
const [isSplashReady, setIsSplashReady] = useState(false);
const _cacheFonts: CacheFontsFn = fonts =>
fonts.map(font => Font.loadAsync(font as any));
const _cacheSplashAssets = () => {
const splashIcon = require(splashIconPath);
return Asset.fromModule(splashIcon).downloadAsync();
};
const _cacheAppAssets = async () => {
SplashScreen.hide();
const fontAssetPromises = _cacheFonts(fontMap);
return Promise.all([...fontAssetPromises]);
};
const _initializeApp = async () => {
// Cache assets
await _cacheAppAssets();
// Check if user is logged in
const sessionId = await SecureStore.getItemAsync(CCSID_KEY);
// Get deep linking params
const params = props.navigation.state.params;
let action: any;
if (params && params.routeName) {
const { routeName, ...routeParams } = params;
action = NavigationActions.navigate({ routeName, params: routeParams });
}
// If not logged in, navigate to Auth flow
if (!sessionId) {
return props.navigation.dispatch(
NavigationActions.navigate({
routeName: 'Onboarding',
action,
})
);
}
// Otherwise, navigate to App flow
return props.navigation.navigate(
NavigationActions.navigate({
routeName: 'App',
action,
})
);
};
if (!isSplashReady) {
return (
<AppLoading
startAsync={_cacheSplashAssets}
onFinish={() => setIsSplashReady(true)}
onError={console.warn}
autoHideSplash={false}
/>
);
}
return (
<View style={{ flex: 1 }}>
<Image source={require(splashIconPath)} onLoad={_initializeApp} />
</View>
);
};
我使用routeName 查询参数创建深层链接,这是执行身份验证检查后要导航到的屏幕的名称(您显然可以添加您需要的任何其他查询参数)。由于我的SplashLoading 屏幕处理加载所有字体/资产以及身份验证检查,因此我需要每个深层链接来路由它。我遇到的问题是,我会手动退出应用程序的多任务处理,点击深层链接 url,然后应用程序崩溃,因为深层链接绕过了 SplashLoading,所以没有加载字体。
上面的方法声明了一个action 变量,如果没有设置它将什么都不做。如果routeName 查询参数不是undefined,我设置action 变量。这使得一旦 Switch 路由器根据 auth(Onboarding 或 App)决定采用哪条路径,该路由就会在退出 auth/splash 加载流程后获取子操作并导航到 routeName。
这是我创建的一个示例链接,它在这个系统上运行良好:
exp://192.168.1.7:19000/--/auth-link?routeName=ForgotPasswordChange&cacheKey=a9b3ra50-5fc2-4er7-b4e7-0d6c0925c536
希望库的作者将来能将其作为本机支持的功能,这样黑客就没有必要了。我也很想看看你的想法!