web-dev-qa-db-fra.com

React navigation didfocus event listener fonctionne différemment entre le composant de classe et le composant fonctionnel

Lorsque je passerai à cet écran, il fera quelques appels API pour récupérer les dernières données. Mais il ne semble pas déclencher l'événement didFocus pour déclencher les appels de l'API lorsque je passe d'une autre pile de navigation avec la version hooks alors que cela fonctionne bien avec la version classe.

Comment puis-je faire en sorte que la version des hooks ait le même comportement que la version de classe?

Quelle est la différence entre ces deux versions?

version du composant de classe

class someScreen extends Component {
    componentDidMount() {
       const {
           navigation,
       } = this.props;

       this.navFocusListener = navigation.addListener('didFocus', () => {
         // do some API calls here
         console.log("class version");
         API_CALL();
       });
    }

    componentWillUnmount() {
        this.navFocusListener.remove();
    }
}

sortie console

transition d'une autre pile de navigation vers cet écran: version de classe

transition entre les écrans d'une même pile: version classe

Version crochets

const someScreen = ({
 navigation,
}) => {
    useEffect(() => {
        const navFocusListener = navigation.addListener('didFocus', () => {
        // do some API calls here
        API_CALL();
        console.log('hooooks');
    });

    return () => {
        navFocusListener.remove();
    };
  }, []);
}

sortie console

transition d'une autre pile de navigation vers cet écran: rien ne s'affiche dans la console

transition entre les écrans d'une même pile: hooooks

BTW, voici la solution de contournement que j'ai trouvée

const someScreen = ({
 navigation,
}) => {
      useEffect(() => {
          const isFocused = navigation.isFocused();

          // manually judge if the screen is focused
          // if did, fire api call
          if (isFocused) {
             // do the same API calls here
             API_CALL();
             console.log('focused section');
          }

          const navFocusListener = navigation.addListener('didFocus', () => {
              // do some API calls here
              API_CALL();
              console.log('listener section');
          });

          return () => {
              navFocusListener.remove();
          };
      }, []);
}

sortie console

transition d'une autre pile de navigation vers cet écran: section ciblée

transition entre les écrans d'une même pile: section d'écoute

11
chitsutote

Je suppose que j'ai trouvé la cause première du comportement incohérent. Il existe un autre hook appelé useLayoutEffect

useLayoutEffect La signature est identique à useEffect, mais elle se déclenche de manière synchrone après toutes les mutations DOM. Utilisez-le pour lire la disposition du DOM et effectuer un nouveau rendu synchrone. Les mises à jour planifiées dans useLayoutEffect seront vidées de manière synchrone, avant que le navigateur ait la possibilité de peindre.

useLayoutEffect bloquera la peinture tandis que useEffect ne le fera pas. Cela confirme et explique ma supposition que l'événement didFocus s'est déclenché, mais cela n'a pas déclenché l'auditeur car il manque le timing

donc dans mon cas, je dois utiliser useLayoutEffect au lieu de useEffect

référence: https://kentcdodds.com/blog/useeffect-vs-uselayouteffecthttps://reactjs.org/docs/hooks-reference.html#uselayouteffect

3
chitsutote