用户注销时如何重置 TabNavigator(从其他屏幕)

IT技术 reactjs react-native react-redux react-navigation react-native-navigation
2021-04-18 02:51:53

这是我的项目文件层次结构

RootTabNavigator
    | AuthStackNavigator // I want to go back to this navigator
          | AuthoScreen
    | Welcome Screen
    | MainTabNavigator // I want to reset MainTabNavigator 
          | FeedStacknavigator
                   | Screen A
          | OtherStackNavigatorOne
                   | Screen E
          | OtherStackNavigatorTwo
                   | Screen D
          | MenuStackNavigator 
                   | Menuo <-I'm here and want to reset to 'MainTabNavigator' 
                             and go BACK to 'AuthScreen'
           | Screen B
                   | Screen C

问题

用户位于 MenuStackNavigator 和 MainTabNavigator 下的 Menuo 屏幕上。

如果用户没有令牌(当用户注销时),用户将返回到身份验证屏幕。

但同时我想重置 MainTabNavigator您可以卸载、执行 NavigationActions.init() 或任何您可以执行的操作。我更喜欢 NavigationActions.init()

我只想将 MainTabNavigator 设置为第一次。

代码

如果没有令牌,我将返回到 Auth Screen(这是有效的)

This code if the part of Menuo Screen

componentWillReceiveProps(nextProps) {
    if ( nextProps.token == undefined || _.isNil(nextProps.token) ) {
      const backAction = NavigationActions.back({
        key: null
      })
      nextProps.navigation.dispatch(backAction);
      ...

(问题)我们如何重置 MainTabNavigator 包括子 StackNavigator?

MainTabNavigator.js

export default TabNavigator(
    {
        Feed: {
          screen: FeedStacknavigator,
        },
        OtherOne: {
          screen: OtherStackNavigatorOne,
        }
        ...
    }, {
        navigationOptions: ({navigation}) => ){
            header: null,
        tabBarIcon: ({focused}) => ...
        ...
    }

可能的解决方案

我也许可以将 MainTabNavigator 从函数更改为类,并在那里处理重置 TabNavigator。(我不确定)。

这一次,我需要一个具体的工作示例。我一直在阅读文档并申请我的应用程序,但我无法解决这个问题。

如果有任何不清楚的地方,请告诉我。

更新

const RootTabNavigator = TabNavigator ({
    Auth: {
      screen: AuthStackNavigator,
    },
    Welcome: {
      screen: WelcomeScreen,
    },
    Main: {
      screen: MainTabNavigator,
    },
  }, {
    navigationOptions: () => ({
     ...
  }
);

export default class RootNavigator extends React.Component {
  componentDidMount() {
    this._notificationSubscription = this._registerForPushNotifications();
  }
3个回答

这在大多数情况下应该有效:

componentWillReceiveProps(nextProps) {
    if ( nextProps.token == undefined || _.isNil(nextProps.token) ) {

        let action = NavigationActions.reset({
            index: 0,
            key: null,
            actions: [
                NavigationActions.navigate({routeName: 'Auth'})
            ]
        });

        nextProps.navigation.dispatch(action);
    }
    ...
}

或者尝试通过自定义操作增强您的导航器:

const changeAppNavigator = Navigator => {
   const router = Navigator.router;

   const defaultGetStateForAction = router.getStateForAction;

   router.getStateForAction = (action, state) => {
       if (state && action.type === "RESET_TO_AUTH") {
          let payLoad = {
              index: 0,
              key: null,
              actions: [NavigationActions.navigate({routeName: "AuthStackNavigator"})]
          };

          return defaultGetStateForAction(NavigationActions.reset(payLoad), state);
          // or this might work for you, not sure:
          // return defaultGetStateForAction(NavigationActions.init(), state)
       }
       return defaultGetStateForAction(action, state);
  };

  return Navigator;
};

const screens = { ... }

RootTabNavigator = changeAppNavigator(TabNavigator(screens, {
  initialRouteName: ...,
  ...
}));

然后在你Menuo Screen做的:

componentWillReceiveProps(nextProps) {
    if ( nextProps.token == undefined || _.isNil(nextProps.token) ) {

        nextProps.navigation.dispatch({type: "RESET_TO_AUTH"});
    ...
当然。它打印Object { "dispatch": [Function anonymous], "goBack": [Function goBack], "navigate": [Function navigate], "setParams": [Function setParams], "state": Object { "key": "id-xxxxx578521-6", "params": undefined, "routeName": "ChangePassword", }, }
2021-05-30 02:51:53
在做之前,this.props.navigation.dispatch({type: "RESET_TO_AUTH"});你能确认一下navigation道具上有吗?
2021-05-31 02:51:53
当我尝试在其他屏幕上调度 ({type: "RESET_TO_AUTH"}) 时,我得到 undefined is not an object (evaluating '_this3._component.setNativeProps') (MenuScreen > ChangePasswordScreen)..
2021-06-03 02:51:53
@JohnBaek 你应该可以在任何导航器上使用它,我在少数情况下尝试过它,为我工作,在我的项目中使用它......
2021-06-18 02:51:53
哦,代码很容易阅读,我明白它是如何工作的!!但是我的 RootTabNavigator 已经定义为类。我们可以对我的 RootTabNavigator 使用相同的逻辑吗?谢谢!
2021-06-21 02:51:53

您需要的是将导航器初始化为初始状态。你可以用NavigationActions.init(). 您可以在此处了解有关导航操作的更多信息

您可以通过创建自定义导航操作来完成此操作,请在此处阅读有关它们的更多信息

这里有一些代码可以为你做到这一点:

// First get a hold of your navigator
const navigator = ...

// Get the original handler
const defaultGetStateForAction = navigator.router.getStateForAction

// Then hook into the router handler
navigator.router.getStateForAction = (action, state) => {

  if (action.type === 'MyCompleteReset') {
     // For your custom action, reset it all
     return defaultGetStateForAction(NavigationActions.init())
  }

  // Handle all other actions with the default handler
  return defaultGetStateForAction(action, state)
}

为了触发您的自定义导航操作,您必须从 React 组件中按如下方式分派它:

  this.props.navigation.dispatch({
      type: "MyCompleteReset",
      index: 0
    })
2021-05-28 02:51:53
我们如何传递 action.type
2021-06-01 02:51:53
我需要具体的工作示例。我希望赏金+200有帮助
2021-06-14 02:51:53
嘿@JohnBaek 查看编辑后的答案。我添加了一个如何触发自定义操作的示例。
2021-06-14 02:51:53

您可以通过扩展路由器来定义自定义导航逻辑。要完成您在问题中的项目文件层次结构中描述的您想要的内容,您可以执行以下操作。

MainTabNavigator.js

...

RootTabNavigator.router.getStateForAction = (action, state) => {
  if (state && action.type === 'GoToAuthScreen') {
    return {
      ...state,
      index: 0,
    };
  }

  return RootTabNavigator.router.getStateForAction(action, state);
};

MainTabNavigator.router.getStateForAction = (action, state) => {
  if (state && action.type === 'GoToAuthScreen') {
    return {
      ...state,
      index: 0,
    };
  }

  return MainTabNavigator.router.getStateForAction(action, state);
};

MenuStackNavigator.router.getStateForAction = (action, state) => {
  if (state && action.type === 'GoToAuthScreen') {
    return {
      ...state,
      index: 0,
    };
  }

  return MenuStackNavigator.router.getStateForAction(action, state);
};

在菜单屏幕文件中

componentWillReceiveProps(nextProps) {
  if ( nextProps.token == undefined || _.isNil(nextProps.token) ) {
    const goToAuthScreen = () => ({
      type: 'GoToAuthScreen',
    });

    nextProps.navigation.dispatch(goToAuthScreen);
    ...
  }
}