Hallo, ich versuche mit navigate
zur nächsten Komponente zu navigieren. Ich verwende react-navigation
für die Navigation zwischen mehreren Komponenten.
Angenommen, ich habe index.Android.js
und DashboardScreen.js
Komponente. Ich versuche, von der Indexkomponente zu der DashboardScreen.js
-Komponente zu navigieren.
Es navigiert, aber die Indexkomponente bleibt immer im Komponentenstapel. Wenn ich zurück drücke, öffnet sich index.Android.js
, was nicht sein sollte. Weiß jemand, wie man dies in react-native
verwaltet. In Android funktioniert finish()
dafür.
navigate("DashboardScreen");
Wenn ich von SplashScreen
zu EnableNotification
navigiere, sollte SplashScreen
zerstört werden, wenn ich von EnableNotification
zu CreateMessage
navigiere, sollte EnableNotification
zerstört werden und wenn ich von CreateMessage
zu DashboardScreen
navigiere, dann CreateMessage
. Bis jetzt wird keine Komponente zerstört.
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"
}
);
Verwenden Sie einfach 'ersetzen' anstelle von 'navigieren'
this.props.navigation.replace('Your Next Component Name')
Zunächst einmal ist die Verwendung von AsyncStorage in einer synchronen Funktion (besonders im Lebenszyklus) eine so schlechte Idee. Normalerweise sollten Sie ASyncStorage an Orten in Ihrer Ordner-/App-Struktur belassen, die für den Ort, an dem Sie auf Daten zugreifen/aufbewahren, sinnvoll sind.
Grundsätzlich fragen Sie nach der Navigation, sobald sich die ASync-Methode auf JEDEM Rendern vollendet hat ... Diejenigen, die neu in RN sind, sollten wissen, dass eine Menge Dinge dazu führen können, dass ein Render ausgelöst wird. In einigen Fällen kann die Renderfunktion mindestens zehn Mal ausgelöst werden, bevor das letzte Rendering abgeschlossen wird. Dies bedeutet, dass Sie diese ASyncStorage-Methode 10-mal ausgelöst hätten ... definitiv etwas, worüber Sie nachdenken müssen, wenn Sie dieses Zeug implementieren. Der .then();
-Teil der AsyncStorage-Funktion wird also mehr oder weniger lange ausgelöst, nachdem der Rendervorgang bereits abgeschlossen ist. Wenn es eine sinnvolle Vorgehensweise wäre, würde ich sagen, dass der return
-Teil der Renderfunktion in die .then((value) => { return ( ... ); });
eingefügt wird. Dies ist jedoch eine noch schlechtere Idee. Grundsätzlich benötigen Sie hier die richtige Lifecycle-Methode und NICHT die Render-Methode.
Jedenfalls, da ich diese Komponentenbibliothek noch nie verwendet habe, kann ich nur helfen, Sie in die richtige Richtung zu bewegen, also hier ... Diese Dokumente auf ihrer Webseite scheinen zu sagen, dass Sie einen Verweis auf den übergebenen Requisitenavigator benötigen zu der Komponente, in der Sie es verwenden. Wenn Sie also den Navigator in dieser Klasse erstellt haben, würden Sie this.refs.whateverYouNamedTheNavigatorReference.navigate('SomeItemName')
verwenden. Wenn Sie sich in der Klasse befinden, die dieser Navigator als Requisite übergeben wurde, verwenden Sie this.props.passNavigatorPropName.navigate('SomeItemName')
. Wie Sie sehen, verwenden Sie die Variablendekonstruktion, um den navigate
-Callback zu erhalten. Ich möchte dies jedoch auf diese Weise tun, da ich gesehen habe, dass Fehler verursacht wurden, indem Sie versehentlich eine alte Version der Navigationsfunktion oder ihrer übergeordneten Referenz abrissen und einen kaskadierenden Fehlereffekt verursachen .
Wenn Sie ASyncStorage in einer Komponentendatei verwenden (würde erneut empfehlen, dies in einer Komponente/Klasse zu speichern, in der auf Ihre Daten in der gesamten App zugegriffen wird ...), und Sie werden es verwenden, um die App zu entscheiden vorwärts/rückwärts navigieren ... definitiv aus der Renderfunktion entfernen und möglicherweise in die Lebenszyklusfunktionen constructor
, componentWillReceiveProps
, componentDidReceiveProps
oder componentWillUpdate
einfügen. Auf diese Weise wird es basierend auf einem Update, einem neu übergebenen Requisitobject oder einmalig ausgelöst, wenn die Komponente erstellt wird. Alles ist besser als jedes einzelne Rendering abzufeuern.
Schließlich weiß ich nicht, was Sie für Ihr StackNavigator
-Routenstapelobjekt eingerichtet haben, aber Sie müssten das Schlüsselwort "DashboardScreen" verwenden, das auf eine Komponente verweist, die ordnungsgemäß importiert wurde. Das Schlüsselwort "DashboardScreen" würde höchstwahrscheinlich in Ihrem StackNavigator
-Objekt eine Verbindung zu einem Komponentenimport herstellen, wie ...
import Dashboard from '../Views/DashboardScreenView';
StackNavigator({
DashboardScreen: {
screen: Dashboard,
path: 'dashboard/:main',
navigationOptions: null,
},
});
Aufgrund Ihrer Anforderungen empfehle ich folgende Einstellungen:
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"
}
);
In Ihrem index.Android.js
rendern Sie die SplashNavigator
.
Die SplashNavigator
wird die SplashScreen
rendern. Der Anfangsstatuswert isReady
ist auf false
gesetzt. Er gibt also einen Ladetext aus, bis der @ProductTour:key
-Wert von AsyncStorage
geladen wird (AsyncStorage
ist eine async-Funktion, und Sie sollten ihn nicht in Ihre Renderfunktion einfügen. Es wird dann Ihren AppNavigator und Ihre EnableNotification
als anfängliche Route darstellen.
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>
);
}
}
Dann ändern Sie auf EnableNotificationScreen
und CreateMessageScreen
Ihre Navigationsroutenfunktion, um NavigationActions.reset
von doc zu verwenden.
Beispiel:
import { NavigationActions } from 'react-navigation';
handleOnPressButton = () => {
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: "CreateMessage" })
]
});
this.props.navigation.dispatch(resetAction);
}
this.props.navigation.replace('Your Next Component Name')
Ja, Sie können den aktuellen Bildschirm vor dem Navigieren zu einem neuen Bildschirm mit Hilfe von NavigationActions beenden. Bitte verweisen Sie auf diesen Link -
Hier gibt es eine einfache Möglichkeit: Verwenden Sie "ersetzen" (Referenzlink repleace in navigation . Sie befinden sich beispielsweise auf dem Bildschirm "Login", Und möchten zum Bildschirm "Home" wechseln. Fügen Sie diesen ein Code im Bildschirm "Login"
<TouchableOpacity onPress={() => { this.login() }}>
<Text}>Click me to Login</Text>
</TouchableOpacity>
und method login:
login(){
this.props.navigation.replace('Home')
}
Bildschirm "Login" wird durch "Home" ersetzt. Drücken Sie in Android die Zurück-Taste => App beenden, kein Bildschirm "Login".
SplashNavigator.js
const SplashNavigator = StackNavigator({
Splash: {
screen: SplashScreen,
navigationOptions: {
header: null}
}
}
});