如何在反应原生中导航到下一个组件时完成当前组件

时间:2017-08-19 14:07:15

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

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

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

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

navigate("DashboardScreen");

当我从SplashScreen导航到EnableNotification时,如果我从SplashScreen导航到EnableNotification,那么CreateMessage应该被销毁EnableNotification应该被销毁,如果我从CreateMessage导航到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"
  }
);

8 个答案:

答案 0 :(得分:4)

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

基本上,当ASync方法基于每个渲染完成自身时,您要求导航... RN的新手应该知道很多东西都可能导致渲染。在某些情况下,渲染函数可以在完成最后一次渲染之前触发(我之前已经多次看过)10次或更多次。这意味着您将已经解雇了ASyncStorage方法10次......在实现这些内容时肯定要考虑一下。所以或多或少,AsyncStorage函数的m部分在渲染完成之后很长时间才会触发。如果这是一种合理的使用方法,我会说将.then();部分的渲染函数放在return内。但这是一个更糟糕的想法。基本上你需要正确的生命周期方法,而不是渲染方法。

无论如何,因为我之前从未使用过这个组件库,所以我只能帮助你朝着正确的方向推动你,所以这里... ... These docs在他们的网页上似乎说你需要一个对道具导航器的引用传递给您正在使用它的组件。因此,如果您在此课程中创建了导航器,则可以使用.then((value) => { return ( ... ); });。如果您在已将此导航器作为道具传递的类中,则使用this.refs.whateverYouNamedTheNavigatorReference.navigate('SomeItemName')。我看到你正在使用变量解构来获得this.props.passNavigatorPropName.navigate('SomeItemName')回调,但是我会谨慎这样做,因为我看到它通过意外地抓住旧版本的导航功能或其父引用而导致错误并导致级联错误效应。

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

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

StackNavigator

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

答案 1 :(得分:3)

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

<强> 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,因此它将呈现加载文本,直到加载@ProductTour:key的{​​{1}}值为止AsyncStorage为异步函数,你不应该把它放在你的渲染功能中)。然后它会渲染您的AppNavigator并将AsyncStorage渲染为初始路径。

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> ); } } EnableNotificationScreen上,将导航路线功能更改为使用doc中的CreateMessageScreen

示例:

NavigationActions.reset

答案 2 :(得分:1)

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

                         <TouchableOpacity onPress={() => { this.login() }}>

                            <Text}>Click me to Login</Text>

                        </TouchableOpacity>

和方法登录:

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

“登录”屏幕将替换为“主页”,在Android中,按“后退”按钮=> app退出,无后退屏幕“登录”

答案 3 :(得分:1)

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

答案 4 :(得分:0)

是的本地反应您可以在NavigationActions的帮助下导航到新屏幕之前完成当前屏幕。请参阅此链接 -

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

答案 5 :(得分:0)

SplashNavigator.js

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

答案 6 :(得分:0)

Just use 'replace' in place of 'navigate'

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

答案 7 :(得分:-1)

从react-navigation导入StackAction和NavigationActions。

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

以下用于执行操作的代码

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

  this.props.navigation.dispatch(navigateAction);
}