J'ai besoin de transmettre les données de mon HomeScreen à mon SecondScreen. Il existe une tonne d'exemples de la façon de le faire si je clique sur un bouton de l'écran d'accueil pour accéder à SecondScreen, mais je ne trouve rien indiquant comment passer à SecondScreen si j'utilise un navigateur d'onglet inférieur v2 pour aller de HomeScreen à SecondScreen. J'ai essayé des screenprops et quelques autres méthodes et j'ai passé environ 8 heures à essayer de le comprendre, mais je n'ai pas pu le faire fonctionner. Une idée comment faire cela? S'il vous plaît, tout indice serait incroyable. Voici mon code:
MainTabNavigator.js:
); } _signInAsync = async () => { let redirectUrl = AuthSession.getRedirectUrl(); let result = await AuthSession.startAsync({ authUrl: `https://www.facebook.com/v2.8/dialog/oauth?response_type=token` + `&client_id=${FB_APP_ID}` + `&redirect_uri=${encodeURIComponent(redirectUrl)}`, }); var token = result.params.access_token await AsyncStorage.setItem('userToken', token); await fetch(`https://graph.facebook.com/me?fields=email,name&access_token=${token}`).then((response) => response.json()).then((json) => { this.props.navigation.navigate('Home', { UserName : json.name, FBID : json.id, email : json.email }); }) .catch(() => { console.log('ERROR GETTING DATA FROM FACEBOOK') }); }; } export default SignInScreen;
HomeScreen.js:
class SignInScreen extends React.Component { static navigationOptions = { title: 'Please sign in', }; render() { return ( <View style={styles.container} contentContainerStyle={styles.contentContainer}> <View> <SocialIcon title='Continue With Facebook' button type='facebook' iconSize="36" onPress={this._signInAsync} /> </View>
SecondScreen.js:
const SomeStack = createStackNavigator({ // config }); <SomeStack screenProps={/* this prop will get passed to the screen components as this.props.screenProps */} />
**** Veuillez trouver les CHOSES QUE J'AI ESSAYÉES ci-dessous: ****
HomeScreen.js: quand je fais cela, il le reçoit dans un premier temps mais passe ensuite null
HomeStack.navigationOptions = { tabBarLabel: 'Home', tabBarIcon: ({ focused }) => ( <MaterialIcons name="home" size={32} /> ), }; <HomeStack screenProps={{DataFromHomeScreen:'data im trying to pass'}}/> HomeStack.path = '';
MaintTabNavigator.js: quand je fais cela, il le reçoit dans un premier temps mais passe ensuite null
render(){ return( <View> //all of my home screen jsx <SecondScreen screenProps={{DataFromHomeScreen : 'data im trying to pass'}}/> </View> ) }
J'ai essayé cinq autres méthodes dont je ne me souviens même pas à ce stade. Je ne veux pas avoir à appeler à nouveau ma base de données dans le deuxième écran pour obtenir des informations sur l'utilisateur. Personne que je connais ne sait réagir ou réagir natif. La documentation React Native sur https://reactnavigation.org/docs/en/stack-navigator .html est au mieux minimal, ne montrant que ce qui suit:
class SecondScreen extends Component { constructor(props){ super(props); } render() return( <View>{this.props.DataFromHomeScreen}</View> ) //....
même si vous consultez les exemples de la documentation et recherchez le mot «screenprop» vous ne verra aucune mention de la fonctionnalité d'accessoire d'écran dans aucun des exemples. Toutes les questions que j'ai vues ne concernent que la façon de passer des accessoires en cliquant sur un bouton, ce qui est facile. Est-ce que ce que j'essaie de faire est possible? Je suis sûr que je ne suis pas la seule personne à utiliser le navigateur d'onglets à avoir récupéré des données dans l'écran d'accueil et à les transmettre à d'autres écrans. Tout conseil aide. merci.
ps. Voici ma classe de connexion qui appelle l'écran d'accueil:
class HomeScreen extends Component { constructor(props){ super(props); } componentDidMount(){ this.setState({DataFromHomeScreen: 'my data that Im trying to send to SecondScreen'}) } //....
const config = Platform.select({ web: { headerMode: 'screen' }, default: {}, }); const HomeStack = createStackNavigator( { Home: HomeScreen, }, config ); HomeStack.navigationOptions = { tabBarLabel: 'Home', tabBarIcon: ({ focused }) => ( <MaterialIcons name="home" size={32} /> ), }; HomeStack.path = ''; const SecondStack= createStackNavigator( { Second: SecondScreen, }, config ); SecondStack.navigationOptions = { tabBarLabel: 'Second screen stuff', tabBarIcon: ({ focused }) => ( <MaterialIcons name="SecondScreenIcon" size={32} /> ), }; SecondStack.path = ''; const tabNavigator = createBottomTabNavigator({ HomeStack, SecondScreen }); tabNavigator.path = ''; export default tabNavigator;
4 Réponses :
Je pense que vous appelez votre base de données dans componentDidMount dans votre composant HomeScreen, (j'ai raison?) et parce qu'un autre composant de la même hiérarchie a besoin des mêmes données, vous devriez envisager de l'envelopper dans un nouveau composant et faire le appelez vos données dans ce composant père, puis vous transmettez les données à tous les enfants qui en ont besoin. Voici la réagir façon de faire les choses . L'état de HomeScreen ne doit pas avoir les données, vos données doivent vivre dans un composant parent dans une hiérarchie supérieure et transmettre les données aux enfants comme accessoires.
De cette façon, lorsque vous créez vos onglets, vous pouvez passer les accessoires en tant que réaction les documents natifs suggèrent:
class Home extends React.Component{ constructor(props){ super(props); this.state = {data: null} } componentDidMount() { //get your props from navigation (your facebook credentials) //your call to database this.setState({data: yourResponseData}); } render(){ const TabNavigator = createBottomTabNavigator( { HomeScreen: props => <HomeScreenStack {...this.state.data} />, SecondStack: props => <SecondStack {...this.state.data} />, }, ); return( <TabNavigator /> ) } } const App = createAppContainer(Home); export default App;
Une autre solution pourrait être d'utiliser une gestion globale de l'état avec Redux ou quelque chose de similaire.
J'espère que cela vous aidera.
Modifier:
import { createBottomTabNavigator, BottomTabBar } from 'react-navigation-tabs'; const TabBarComponent = (props) => (<BottomTabBar {...props} />); const TabScreens = createBottomTabNavigator( { tabBarComponent: props => <TabBarComponent {...props} style={{ borderTopColor: '#605F60' }} />, }, );
J'utilise react-navigation v2 donc je n'ai pas d'onglets de react-navigation. J'appelle l'écran d'accueil à partir d'un SignInScreen qui est l'endroit où j'obtiens les informations d'authentification FB, une fois que j'arrive à HomeScreen, j'appelle ma base de données avec ces informations d'authentification FB de SigninScreen. Je vois ce que vous dites sur la nécessité d'utiliser un composant d'ordre supérieur, mais je ne sais pas comment l'implémenter étant donné ma structure.
Luis, j'ai ajouté ma classe SignIn au bas de ma question si cela aide
J'ai modifié ma réponse pour ajouter un composant Home qui implémente cette structure.
J'ai essayé votre réponse modifiée et j'obtiens cette erreur dans l'écran d'accueil: 'violation invariante: l'accessoire de navigation est manquant pour ce navigateur. Dans react-navigation 3, vous devez configurer votre conteneur d'application directement. au fait, je viens de mettre la partie
où dois-je mettre
Dans ce cas, avec React Navigation 3, vous avez besoin d'un conteneur d'applications, jetez un œil à ma dernière modification. ce code doit être à la fin de votre fichier, vous devez d'abord créer votre composant HomeScreenStack et votre SecondStack, cette partie de votre code reste sans modifications, cela devrait fonctionner comme vous l'avez posté, utilisez votre HomeStack et SecondStack tels quels dans la fonction createBottomTabNavigator . Sachez dans ces modules qu'au premier rendu, les données seront nulles.
Utilisez this.props.navigation.navigate
.
Dans votre HomeScreen
, une fois que vous avez les données que vous souhaitez envoyer, accédez à SecondScreen comme ceci:
const username = this.props.navigation.getParam('UserName', '') const fbid = this.props.navigation.getParam('FBID', 0) const email = this.props.navigation.getParam('email', '')
Pour y accéder dans SecondScreen
chaque fois qu'il est accédé à l'aide des accessoires de navigation, vous pouvez utiliser NavigationEvents
avec this. props.navigation.getParam
.
/* your imports */ import { NavigationEvents } from 'react-navigation'; export default class SecondScreen extends React.Component { /* your methods and properties */ render() { <View> <NavigationEvents onDidFocus={() => this.setState({ data: this.props.navigation.getParam('data', {}) })} /> { /* your SecondScreen render code */ } </View> } }
Modifier: par exemple, avec votre implémentation SignInScreen
, pour accéder aux accessoires , utilisez:
this.props.navigation.navigate('Second', { data: yourData })
L'appel de this.props.navigation.navigate m'amènera-t-il au deuxième écran lorsque je l'appellerai? Je ne veux pas être redirigé vers le deuxième écran, sauf si je clique sur le bouton du navigateur de l'onglet inférieur
Dans ce cas, je recommanderais d'enregistrer les données dans AsyncStorage
et de les récupérer sur componentDidMount
dans le deuxième écran
Ce sera un tableau 2d et devra y accéder à partir de plusieurs écrans. ceci est juste un exemple simplifié
Redux serait la meilleure solution pour cette route, mais AsyncStorage
pourrait toujours fonctionner pour ce cas d'utilisation. Pour éviter d'avoir à réécrire pour l'obtenir sur componentDidMount
à chaque fois, vous pouvez écrire un HOC ( reactjs.org/docs/higher-order-components.html ) qui prendra le composant cible, récupérera les données de AsyncStorage
lors du montage, puis transmettra le données comme accessoires normaux pour le composant cible.
J'ai fini par utiliser Redux, il ne m'a fallu que 100 lectures et tentatives de l'apprendre, mais une fois que je l'ai appris, c'est incroyable et simple.
Si cela résout le cas d'utilisation, pouvez-vous fournir un exemple à l'auteur?
Voici l'approche de base que j'utilise:
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; const TestComponent = (props) => { return <Text>{`TestComponent: ${props.name}`}</Text>; }; const Home = () => { const Tab = createBottomTabNavigator(); return ( <View style={{flex: 1}}> <Tab.Navigator> <Tab.Screen name="Screen 1"> {() => <TestComponent name="test 1" />} </Tab.Screen> <Tab.Screen name="Screen 2"> {() => <TestComponent name="test 2" />} </Tab.Screen> </Tab.Navigator> </View> ); };
Notez que pour passer les accessoires à un écran
, j'utilise une fonction enfant au lieu de passer un valeur au composant
. La fonction enfant peut alors renvoyer le composant souhaité dans la syntaxe à laquelle vous êtes habitué, qui dispose des accessoires disponibles. Dans ce cas, les accessoires sont le simple nom
, mais vous pouvez le développer pour gérer votre état.
Essayez-vous de transmettre les données en appuyant sur le bouton de l'onglet inférieur pour
SecondScreen
, ou via un bouton dansHomeScreen
?Je récupère les données utilisateur sur l'écran d'accueil de ma base de données. Idéalement, je l'enverrais à SecondScreen pour rendre des trucs dès que j'obtiens les données de la fonction de récupération dans l'écran d'accueil. Je pourrais me contenter d'envoyer les données lorsque je clique sur le bouton de l'onglet inférieur SecondScreen si la première option n'est pas possible.