【问题标题】:How to finish current component while navigating to next component in react native如何在本机反应中导航到下一个组件时完成当前组件
【发布时间】:2017-08-19 14:07:14
【问题描述】:

您好,我正在尝试使用 navigate 函数导航到下一个组件。我正在使用react-navigation 在多个组件之间进行导航。

假设我有 index.android.jsDashboardScreen.js 组件。我正在尝试从索引组件导航到 DashboardScreen.js 组件。

它正在导航,但索引组件始终保留在组件堆栈中。当我按回然后它打开index.android.js 这不应该。有谁知道如何在react-native 管理这个。在 Android 中,finish() 适用于此。

navigate("DashboardScreen");

当我从SplashScreen 导航到EnableNotification 时,SplashScreen 应该被销毁,如果我从EnableNotification 导航到CreateMessage,那么EnableNotification 应该被销毁,如果我从@987654336 导航@ 到 DashboardScreen 然后 CreateMessage 应该被销毁。到目前为止,没有任何组件被销毁。

index.android.js

class SplashScreen extends Component {
  render() {
    if (__DEV__) {
      console.disableYellowBox = true;
    }

    const { navigate } = this.props.navigation;

    AsyncStorage.getItem("@ProductTour:key").then(value => {
      console.log(value);
      if (value) {
        navigate("DashboardScreen");
      }
    });

    return (
     ....
    );
  }
}

const App = StackNavigator(
  {
    Splash: {
      screen: SplashScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    },
    EnableNotification: {
      screen: EnableNotificationScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    },
    CreateMessage: {
      screen: CreateMessageScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    },
    DashboardScreen: {
      screen: DashboardScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    }
  },
  {
    initialRouteName: "Splash"
  }
);

【问题讨论】:

    标签: android react-native react-native-android react-navigation


    【解决方案1】:

    只需使用 'replace' 代替 'navigate'

    this.props.navigation.replace('Your Next Component Name')
    

    【讨论】:

      【解决方案2】:

      首先,在同步函数(尤其是生命周期函数)中使用 AsyncStorage 是个坏主意。您通常应该将 ASyncStorage 保留在您的文件夹/应用程序结构中对您访问/保存数据的位置有意义的位置,但由于这不是问题,我将在这里快速提及它......

      基本上,一旦 ASync 方法根据每个渲染完成自身,您就会要求导航……那些刚接触 RN 的人应该知道,很多事情都会导致渲染触发。在某些情况下,渲染函数可以在最后一次渲染完成之前触发(我以前见过很多次)10 次或更多次。这意味着您将触发该 ASyncStorage 方法 10 次......在实现这些东西时绝对需要考虑一些事情。所以或多或少,AsyncStorage 函数的.then(); 部分在渲染完成之后很久就会触发。如果这是一种合理的使用方法,我会说将渲染函数的return 部分放在.then((value) => { return ( ... ); }); 中。但这是一个更糟糕的想法。基本上你需要正确的生命周期方法,而不是渲染方法。

      无论如何,因为我从来没有使用过这个组件库,所以我只能帮助你朝着正确的方向前进,所以这里......These docs 在他们的网页上似乎说你需要参考传递下来的道具导航器到您正在使用它的组件。因此,如果您在此类中创建了导航器,您将使用this.refs.whateverYouNamedTheNavigatorReference.navigate('SomeItemName')。如果您在已通过此导航器作为道具的班级,则使用this.props.passNavigatorPropName.navigate('SomeItemName')。我看到您正在使用变量解构来获取 navigate 回调,但我会谨慎这样做,因为我已经看到它通过意外抓取旧版本的导航函数或其父引用并导致级联而导致错误错误效果。

      此外,如果您要在组件文件中使用 ASyncStorage(同样,建议将其放在组件/类中,您的数据可以在整个应用程序中访问...)并且您将使用它来决定应用程序应该向前/向后导航...绝对将其从渲染函数中删除,并将其放入 constructorcomponentWillReceivePropscomponentDidReceivePropscomponentWillUpdate 生命周期函数中。这样,它会根据更新、新传递的 prop obj 或组件构建时触发。任何事情都比每次渲染都触发它要好。

      最后,我不知道您为StackNavigator 路由堆栈对象设置了什么,但您需要在其中使用“DashboardScreen”关键字指向已正确导入的实际组件。 “DashboardScreen”关键字很可能会在您的StackNavigator 对象中连接到某些组件导入,如下所示...

      import Dashboard from '../Views/DashboardScreenView';

      StackNavigator({
        DashboardScreen: {
          screen: Dashboard,
          path: 'dashboard/:main',
          navigationOptions: null,
        },
      });
      

      【讨论】:

      • 谢谢。假设我有一个组件EnableNotification,我从中调用navigate("CreateMessage") 来打开CreateMessage 组件。它正在启动一个组件,但没有完成EnableNotification 组件。这就是我正在寻找的。有什么方法可以销毁 EnableNotification
      • 顺便说一句,您的建议真的很可观。我不知道如何在其他 js 文件中声明 AsyncStorage 并在我的组件中使用它?你能添加一些sn-p代码行吗?
      • 对不起。我认为这个问题实际上具有误导性。它应该被指定为“在 AsyncStorage 回调中”。但也许这不是他遇到的问题。我不知道将您的答案作为答案还是作为评论是否更好。因为您的答案集中在“在 AsyncStorage 回调内”范围
      • 真正的答案是使用navigation.dispatch。你为什么没有提到它令人困惑。我认为这是一个老问题很好考虑
      • 因为我不熟悉此人使用的软件包,只能提供明显的观察结果,其他 4 人认为这些观察结果足以支持投票。这不是选定的答案。
      【解决方案3】:

      这里有一个简单的方法:使用“替换”(参考链接repleace in navigation,例如你在屏幕“登录”, 并且您想移动到屏幕“主页”,将此代码插入屏幕“登录”

                               <TouchableOpacity onPress={() => { this.login() }}>
      
                                  <Text}>Click me to Login</Text>
      
                              </TouchableOpacity>
      

      及方法登录:

      login(){
        this.props.navigation.replace('Home')
       }
      

      屏幕“登录”将被“主页”替换,在Android中,按返回按钮=>应用退出,没有返回屏幕“登录”

      【讨论】:

        【解决方案4】:

        根据您的要求,我建议进行以下设置:

        SplashNavigator.js

        const SplashNavigator = StackNavigator({
          Splash: {
            screen: SplashScreen,
            navigationOptions: {
              header: {
                visible: false
              }
            }
          }
        });
        

        AppNavigator.js

        const AppNavigator = StackNavigator(
          {
            EnableNotification: {
              screen: EnableNotificationScreen,
              navigationOptions: {
                header: {
                  visible: false
                }
              }
            },
            CreateMessage: {
              screen: CreateMessageScreen,
              navigationOptions: {
                header: {
                  visible: false
                }
              }
            },
            Dashboard: {
              screen: DashboardScreen,
              navigationOptions: {
                header: {
                  visible: false
                }
              }
            }
          },
          {
            initialRouteName: "EnableNotification"
          }
        );
        

        在您的index.android.js 中,您将渲染SplashNavigator

        SplashNavigator 将渲染SplashScreen。它的初始状态值isReady 设置为false,因此它将渲染加载文本,直到加载来自AsyncStorage@ProductTour:key 值(AsyncStorage 是异步函数,你不应该把它放在你的渲染函数中)。然后它将呈现您的 AppNavigator 并将您的 EnableNotification 呈现为初始路由。

        class SplashScreen extends Component {
          constructor() {
            super(props);
            this.state = {
              isReady: false,
            }
          }
        
          componentDidMount() {
            AsyncStorage.getItem("@ProductTour:key").then(value => {
              console.log(value);
              // you will need to handle case when `@ProductTour:key` is not exists
              this.setState({
                isReady: true,
              });
            });
          }
        
          render() {
            const { isReady } = this.state;
            return (
              <View style={{flex: 1}}>
                {
                  isReady ?
                  <AppNavigator />
                  : <Text>Loading</Text>
                }
              </View>
            );
          }
        }
        

        然后在EnableNotificationScreenCreateMessageScreen 上,将导航路线功能从doc 更改为使用NavigationActions.reset

        例子:

        import { NavigationActions } from 'react-navigation';
        
        handleOnPressButton = () => {
          const resetAction = NavigationActions.reset({
            index: 0,
            actions: [
              NavigationActions.navigate({ routeName: "CreateMessage" })
            ]
          });
          this.props.navigation.dispatch(resetAction);
        }
        

        【讨论】:

        • 谢谢@alpha。我认为仍然缺少一些要点。假设我有一个组件EnableNotification,我从中调用navigate("CreateMessage") 来打开CreateMessage 组件。它正在启动一个组件,但没有完成EnableNotification 组件。这就是我正在寻找的。有什么方法可以销毁EnableNotification
        • @Williams 我不太明白你的问题,你能告诉我们你的导航流程是什么以及用户如何导航到EnableNotification 屏幕。
        • 它以SplashScreen开头 -> EnableNotification -> CreateMessage -> DashboardScreen。我在每个组件上都有按钮,点击它我打电话给navigate(name_of_the_component。它可以工作,但组件没有被破坏。
        • @Williams 所以你想要的是步骤向导,用户导航到DashboardScreen 后用户无法返回,对吗?
        • 不。当我从SplashScreen 导航到EnableNotification 时,SplashScreen 应该被销毁,如果我从EnableNotification 导航到CreateMessage,那么EnableNotification 应该被销毁,如果我从CreateMessage 导航到@ 987654358@ 然后CreateMessage 应该被销毁。截至目前,没有任何组件被销毁
        【解决方案5】:
        this.props.navigation.replace('Your Next Component Name')
        

        【讨论】:

        • 请简要说明这一行的作用以及为什么它有助于解决问题。
        • 使用这个....当前组件将从导航堆栈中删除,并控制跳转到您提到的下一个组件...替换(“您的组件)
        【解决方案6】:

        是的,在 react native 中,您可以在 NavigationActions 的帮助下导航到新屏幕之前完成当前屏幕。请参考此链接-

        http://androidseekho.com/others/reactnative/finish-current-screen-on-navigating-another-in-react-native/

        【讨论】:

          【解决方案7】:

          SplashNavigator.js

          const SplashNavigator = StackNavigator({
            Splash: {
              screen: SplashScreen,
              navigationOptions: {
                header: null}
              }
            }
          });
          

          【讨论】:

            【解决方案8】:

            从 react-navigation 导入 StackActions 和 NavigationActions。

            import { StackActions, NavigationActions } from 'react-navigation';
            

            下面是执行动作的代码

            navigateToHomeScreen = () => {
              const navigateAction = StackActions.reset({
                index: 0,
                actions: [NavigationActions.navigate({ routeName: "HomeScreen" })],
              });
            
              this.props.navigation.dispatch(navigateAction);
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-07-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多