web-dev-qa-db-fra.com

La fonction `componentDidMount ()` n'est pas appelée après la navigation

J'utilise stackNavigator pour naviguer entre les écrans. J'appelle deux API dans la fonction componentDidMount() dans ma deuxième activité. Lorsque je le charge pour la première fois, il est chargé avec succès. Ensuite, j'appuie sur le bouton de retour pour revenir à la première activité. Ensuite, si je vais à nouveau à la deuxième activité, les API ne sont pas appelées et j'obtiens une erreur de rendu. Je ne trouve aucune solution à cela. Toute suggestion serait appréciée.

17
hitttt

Si quelqu'un vient ici en 2019, essayez ceci:

import {NavigationEvents} from 'react-navigation';

Ajoutez le composant à votre rendu:

<NavigationEvents onDidFocus={() => console.log('I am triggered')} />

Désormais, cet événement onDidFocus sera déclenché à chaque fois que la page se concentrera bien qu'elle provienne de goBack () ou de la navigation.

37
Jithesh Kt

Si la syntaxe votée qui utilise le composant NavigationEvents ne fonctionne pas, vous pouvez essayer avec ceci:

// no need to import anything more

// define a separate function to get triggered on focus
onFocusFunction = () => {
  // do some stuff on every screen focus
}

// add a focus listener onDidMount
async componentDidMount () {
  this.focusListener = this.props.navigation.addListener('didFocus', () => {
    this.onFocusFunction()
  })
}

// and don't forget to remove the listener
componentWillUnmount () {
  this.focusListener.remove()
}
8
vitosorriso

React-navigation maintient le composant monté même si vous naviguez entre les écrans. Vous pouvez utiliser le composant pour réagir à ces événements:

<NavigationEvents
  onDidFocus={() => console.log('hello world')}
/>

Plus d'informations sur ce composant ici .

4
SebLambla

La documentation React-navigation décrit explicitement ce cas :

Considérons un navigateur de pile avec les écrans A et B. Après avoir navigué vers A, son componentDidMount est appelé. En poussant B, son componentDidMount est également appelé, mais A reste monté sur la pile et son componentWillUnmount n'est donc pas appelé.

En revenant de B à A, componentWillUnmount de B est appelé, mais componentDidMount de A n'est pas parce que A est resté monté tout le temps.

Il y a maintenant 3 solutions pour cela:

Abonnement aux événements du cycle de vie

...

React Navigation émet des événements pour filtrer les composants qui s'y abonnent. Vous pouvez vous abonner à quatre événements différents: willFocus, willBlur, didFocus et didBlur. En savoir plus à leur sujet dans la référence API.

Beaucoup de vos cas d'utilisation peuvent être couverts par le composant withNavigationFocus d'ordre supérieur, le composant <NavigationEvents /> Ou le crochet useFocusState.

  1. le withNavigationFocus composant d'ordre supérieur
  2. le composant <NavigationEvents />
  3. le hook useFocusState ( obsolète )

withNavigationFocus composant d'ordre supérieur

import React from 'react';
import { Text } from 'react-native';
import { withNavigationFocus } from 'react-navigation';

class FocusStateLabel extends React.Component {
  render() {
    return <Text>{this.props.isFocused ? 'Focused' : 'Not focused'}</Text>;
  }
}

// withNavigationFocus returns a component that wraps FocusStateLabel and passes
// in the navigation prop
export default withNavigationFocus(FocusStateLabel);

Composant <NavigationEvents />

import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';

const MyScreen = () => (
  <View>
    <NavigationEvents
      onWillFocus={payload => console.log('will focus', payload)}
      onDidFocus={payload => console.log('did focus', payload)}
      onWillBlur={payload => console.log('will blur', payload)}
      onDidBlur={payload => console.log('did blur', payload)}
    />
    {/*
      Your view code
    */}
  </View>
);

export default MyScreen;

useFocusState hook

Installez d'abord la bibliothèque yarn add react-navigation-hooks

import { useNavigation, useNavigationParam, ... } from 'react-navigation-hooks'

function MyScreen() {   const focusState = useFocusState();   return <Text>{focusState.isFocused ? 'Focused' : 'Not Focused'}</Text>; }

Voici ma solution personnelle, en utilisant onDidFocus() et onWillFocus() pour effectuer le rendu uniquement lorsque les données ont été extraites de votre API:

import React, { PureComponent } from "react";
import { View } from "react-native";
import { NavigationEvents } from "react-navigation";

class MyScreen extends PureComponent {
  state = {
    loading: true
  };

  componentDidMount() {
    this._doApiCall();
  }

  _doApiCall = () => {
    myApiCall().then(() => {
      /* Do whatever you need */
    }).finally(() => this.setState({loading: false}));
  };

  render() {
    return (
      <View>
        <NavigationEvents 
              onDidFocus={this._doApiCall} 
              onWillFocus={() => this.setState({loading: true})}
        />
        {!this.state.loading && /*
        Your view code
        */}
      </View>
    );
  }
}

export default MyScreen;
3
Kruupös

Dans React, componentDidMount n'est appelé que lorsque le composant est monté. Je pense que ce que vous essayez de faire est d'appeler votre API lors du retour dans StackNavigator. Vous pouvez passer une fonction de rappel comme paramètre lorsque vous appelez naviguer comme ceci sur l'écran parent:

  navigate("Screen", {
     onNavigateBack: this.handleOnNavigateBack
  }); 
  handleOnNavigateBack = () => {//do something};

Et sur l'écran enfant

this.props.navigation.state.params.onNavigateBack();
this.props.navigation.goBack();
0
Suyog K.C

Vous souhaitez effectuer quelque chose après chaque navigation vers un composant à l'aide de drawernavigator ou stacknavigator; à cet effet, NavigationEvents convient mieux que componentDidMount.

import {NavigationEvents} from "react-navigation";
<NavigationEvents onDidFocus={()=>alert("Hello, I'm focused!")} />

Remarque : si vous souhaitez effectuer la tâche à chaque fois après vous être concentré sur un composant à l'aide de la navigation dans les tiroirs ou de la navigation dans la pile, puis à l'aide de NavigationEvents est une meilleure idée. Mais si vous souhaitez effectuer la tâche une fois, vous devez utiliser componenetDidMount.

0
Taohidul Islam