web-dev-qa-db-fra.com

Réagissez navigation goback () et mettez à jour l'état parent

J'ai une page qui rendra le nom de l'utilisateur s'il est connecté ou l'option "Créer un compte" ou "Connexion" si ce n'est pas le cas. Écran comme ci-dessous

 enter image description here

Ils peuvent accéder à la page "Connexion" ou "Créer un compte". Après s'être connecté ou enregistré avec succès, il ira à cette page et affichera le nom d'utilisateur. Écran comme ci-dessous

 enter image description here

Actuellement, je stocke les données utilisateur dans la variable AsyncStorage. Je souhaite mettre à jour ce champ une fois que l'utilisateur s'est connecté avec succès ou s'inscrire lorsqu'il redirige depuis la page.

Comment puis-je atteindre cet objectif? 

est-il possible de passer param à partir de navigate.goback() et le parent peut écouter les params et mettre à jour son état?

21
Darren Lau

Vous pouvez passer une fonction de rappel en paramètre lorsque vous appelez, naviguez comme ceci:

  const DEMO_TOKEN = await AsyncStorage.getItem('id_token');
  if (DEMO_TOKEN === null) {
    this.props.navigation.navigate('Login', {
      onGoBack: () => this.refresh(),
    });
    return -3;
  } else {
    this.doSomething();
  }

Et définissez votre fonction de rappel:

refresh() {
  this.doSomething();
}

Ensuite, dans la vue de connexion/enregistrement, avant goBack, vous pouvez faire ceci:

await AsyncStorage.setItem('id_token', myId);
this.props.navigation.state.params.onGoBack();
this.props.navigation.goBack();
38
Zhang Buzz

est-il possible de passer param à partir de navigate.goback() et le parent peut écouter les params et mettre à jour son état?

Vous pouvez passer une fonction de rappel en tant que paramètre (comme indiqué dans d'autres réponses). 

Voici un exemple plus clair, lorsque vous naviguez de A à B et que vous souhaitez que B transmette des informations à A, vous pouvez passer un rappel (ici onSelect):

ViewA.js

import React from "react";
import { Button, Text, View } from "react-native";

class ViewA extends React.Component {
  state = { selected: false };

  onSelect = data => {
    this.setState(data);
  };

  onPress = () => {
    this.props.navigate("ViewB", { onSelect: this.onSelect });
  };

  render() {
    return (
      <View>
        <Text>{this.state.selected ? "Selected" : "Not Selected"}</Text>
        <Button title="Next" onPress={this.onPress} />
      </View>
    );
  }
}

ViewB.js

import React from "react";
import { Button } from "react-native";

class ViewB extends React.Component {
  goBack() {
    const { navigation } = this.props;
    navigation.goBack();
    navigation.state.params.onSelect({ selected: true });
  }

  render() {
    return <Button title="back" onPress={this.goBack} />;
  }
}

Chapeau pour debrice _ - Reportez-vous à https://github.com/react-navigation/react-navigation/issues/288#issuecomment-315684617

16
gihanchanuka

J'étais confronté à un problème similaire, alors voici comment je l'ai résolu en approfondissant les détails.

La première option consiste à revenir au parent avec des paramètres, définissez simplement une fonction de rappel dans celle-ci comme ceci dans le composant parent:

updateData = data => {
  console.log(data);
  alert("come back status: " + data);
  // some other stuff
};

et accédez à l'enfant:

onPress = () => {
  this.props.navigation.navigate("ParentScreen", {
    name: "from parent",
    updateData: this.updateData
  });
};

Maintenant chez l'enfant, on peut l'appeler:

 this.props.navigation.state.params.updateData(status);
 this.props.navigation.goBack();

Option deux. Afin d'obtenir des données à partir de n'importe quel composant, comme l'a expliqué l'autre réponse, AsyncStorage peut être utilisé de manière synchrone ou non.

Une fois les données sauvegardées, elles peuvent être utilisées n’importe où. 

// to get
AsyncStorage.getItem("@item")
  .then(item => {
    item = JSON.parse(item);
    this.setState({ mystate: item });
  })
  .done();
// to set
AsyncStorage.setItem("@item", JSON.stringify(someData));

ou bien utilisez une fonction asynchrone pour la mettre à jour automatiquement quand elle obtient une nouvelle valeur.

this.state = { item: this.dataUpdate() };
async function dataUpdate() {
  try {
    let item = await AsyncStorage.getItem("@item");
    return item;
  } catch (e) {
    console.log(e.message);
  }
}

Voir le docs AsyncStorage pour plus de détails.

8
Nerius Jok

Pour ceux qui ne veulent pas gérer via des accessoires, essayez ceci. Il appellera à chaque fois que cette page apparaîtra. 

Remarque * (il ne s’agit pas uniquement de goBack mais il appelle chaque fois que vous entrez

import { NavigationEvents } from 'react-navigation';

    render() {
            return (
              <View style={{ flex: 1 }}>
                <NavigationEvents
                  onWillFocus={() => {
                    // Do your things here
                  }}
                />
              </View>
            );
          }
2
Sagar Chavada

EDITED: La meilleure solution consiste à utiliser NavigationEvents , vous n'avez pas besoin de créer manuellement des écouteurs :)

L'appel d'une fonction de rappel n'est pas vivement recommandé. Vérifiez cet exemple à l'aide d'un écouteur (n'oubliez pas de supprimer tous les écouteurs de composantWillUnMount avec cette option)

Composant A

navigateToComponentB() {
  const { navigation } = this.props
  this.navigationListener = navigation.addListener('willFocus', payload => {
    this.navigationListener.remove()
    const { state } = payload
    const { params } = state
    //update state with the new params
    const { otherParam } = params
    this.setState({ otherParam })
  })
  navigation.Push('ComponentB', {
    returnToRoute: navigation.state,
    otherParam: this.state.otherParam
  })
}

Commponent B

returnToComponentA() {
  const { navigation } = this.props
  const { routeName, key } = navigation.getParam('returnToRoute')
  navigation.navigate({ routeName, key, params: { otherParam: 123 } })
}

Pour plus d'informations sur l'exemple précédent: https://github.com/react-navigation/react-navigation/issues/288#issuecomment-378412411

Cordialement, Nicholls

1
jdnichollsc

Je viens d'utiliser la fonction de navigation standard, donnant le nom de l'itinéraire ViewA et transmettant les paramètres, faisant exactement ce que goBack aurait fait.

this.props.navigation.navigate("ViewA", 
{
     param1: value1, 
     param2: value2
});
0
morgan_il