React native 反应导航:与身份验证的深度链接
我正在使用react native和react导航库构建一个移动应用程序,用于管理我应用程序中的导航。现在,我的应用程序看起来像这样:React native 反应导航:与身份验证的深度链接,react-native,react-navigation,deep-linking,React Native,React Navigation,Deep Linking,我正在使用react native和react导航库构建一个移动应用程序,用于管理我应用程序中的导航。现在,我的应用程序看起来像这样: App [SwitchNavigator] Splash [Screen] Auth [Screen] MainApp [StackNavigator] Home [Screen] (/home) Profile [Screen] (/profile)
App [SwitchNavigator]
Splash [Screen]
Auth [Screen]
MainApp [StackNavigator]
Home [Screen] (/home)
Profile [Screen] (/profile)
Notifications [Screen] (/notifications)
我已经为屏幕主页
、配置文件
和通知
集成了与上述模式的深度链接,并按预期工作。我面临的问题是如何在使用深度链接时管理用户的身份验证。现在每当我打开深层链接(myapp://profile
例如)无论我是否经过身份验证,应用程序都会在屏幕上显示我。我想让它做的是在AsyncStorage
之前检查是否有userToken
,如果没有或不再有效,则只需在Auth
屏幕上重定向即可
我设置身份验证流的方式与前面描述的几乎完全相同。因此,当我的应用程序启动时,Splash
屏幕检查用户的手机中是否有有效的令牌,并在Auth
屏幕或Home
屏幕上发送给他
目前我提出的唯一解决方案是将每个深层链接指向Splash
,对我的用户进行身份验证,然后解析链接以导航到良好的屏幕。
例如,当用户打开myapp://profile
,我在Splash
上打开应用程序,验证令牌,然后解析url(/profile
),最后重定向到Auth
或profile
这是一个好方法,还是react导航提供了一个更好的方法?他们网站上的页面有点轻
谢谢你的帮助 我的设置与你的类似。我遵循并设置了我的Auth流,所以我有点失望,因为获得通过它的深层链接也是一个挑战。我可以通过定制我的主开关导航器来实现这一点,这种方法与您所说的目前的解决方案类似。我只是想与大家分享我的解决方案,所以这里有一个具体的例子,说明如何才能开始工作。我的主开关导航器是这样设置的(我也在使用TypeScript,所以如果不熟悉类型定义,请忽略它们): 要通过身份验证流路由的任何深度链接都需要以
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>
);
};
export const SplashLoading=(道具:NavigationScreenProps)=>{
const[isSplashReady,setIsSplashReady]=useState(false);
const\u cacheFonts:CacheFontsFn=fonts=>
fonts.map(font=>font.loadAsync(任何字体));
const_cacheSplashAssets=()=>{
常量splashIcon=require(splashIconPath);
return Asset.fromModule(splashIcon).downloadAsync();
};
const\u cacheAppAssets=async()=>{
SplashScreen.hide();
const fontAssetPromises=\u缓存字体(fontMap);
返回承诺。所有([…fontAssetPromises]);
};
const\u initializeApp=async()=>{
//缓存资产
等待_cacheAppAssets();
//检查用户是否已登录
const sessionId=wait SecureStore.getItemAsync(CCSID_键);
//获取深度链接参数
const params=props.navigation.state.params;
让行动:任何;
if(params&¶ms.routeName){
const{routeName,…routeParams}=params;
action=NavigationActions.navigate({routeName,params:routeParams});
}
//如果未登录,请导航到验证流
if(!sessionId){
返回props.navigation.dispatch(
导航({
routeName:‘入职’,
行动,
})
);
}
//否则,请导航到应用程序流
返回props.navigation.navigate(
导航({
routeName:“应用程序”,
行动,
})
);
};
如果(!isSplashReady){
返回(
setIsSplashReady(真)}
onError={console.warn}
autoHideSplash={false}
/>
);
}
返回(
);
};
我使用routeName
query参数创建深层链接,这是执行身份验证检查后要导航到的屏幕名称(显然,您可以添加所需的任何其他查询参数)。由于我的SplashLoading
屏幕处理加载所有字体/资源以及身份验证检查,因此我需要每个深层链接来通过它。我面临的问题是,我会手动退出多任务应用程序,点击一个深度链接url,然后让应用程序崩溃,因为深度链接绕过了SplashLoading
,所以字体没有加载
上面的方法声明了一个action
变量,如果不设置该变量,它将不会起任何作用。如果routeName
query参数不是undefined
,我将设置action
变量。这使得一旦交换机路由器基于身份验证(登录
或应用程序
)决定采用哪条路径,该路由就会获得子操作,并在退出身份验证/初始加载流后导航到路由名称
下面是我创建的一个示例链接,该链接在该系统中运行良好:
exp://192.168.1.7:19000/--/身份验证链接?routeName=ForgotPasswordChange&cacheKey=a9b3ra50-5fc2-4er7-b4e7-0d6c0925c536
希望图书馆的作者将来能让这成为一个本机支持的特性,这样就没有必要进行黑客攻击了。我也很想看看你有什么想法 我最终使用一个自定义URI来拦截deeplink启动,然后将这些参数传递到预期的路由。我的加载屏幕处理身份验证检查
const previousGetActionForPathAndParams = AppContainer.router.getActionForPathAndParams
Object.assign(AppContainer.router, {
getActionForPathAndParams (path, params) {
if (path === 'auth' && params.routeName && params.userId ) {
// returns a profile navigate action for myApp://auth?routeName=chat&userId=1234
return NavigationActions.navigate({
routeName: 'Loading',
params: { ...params, path },
})
}
return previousGetActionForPathAndParams(path, params)
},
})
然后,在我的加载路径中,我像普通一样解析参数,但随后将其路由到预期位置,再次传递它们
const userId = this.props.navigation.getParam('userId')
在我这方面,我实现了这一点,而无需手动解析路由以提取路径和参数。 以下是步骤:
- 获取导航ac
const userId = this.props.navigation.getParam('userId')