Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
React native 反应导航:与身份验证的深度链接_React Native_React Navigation_Deep Linking - Fatal编程技术网

React native 反应导航:与身份验证的深度链接

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)

我正在使用react native和react导航库构建一个移动应用程序,用于管理我应用程序中的导航。现在,我的应用程序看起来像这样:

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')