1
votes

Appel de fonction async au composant parent

J'ai ce composant

const Child = ({ functionFromStore, functionFromParent, closeModal }) => {
    async function foo() {
        try {
          await ...;
          functionFromStore();
          functionFromParent();
        } catch (error) {
          ....
        }
    }

    const bar = () => {
        foo();
        closeModal();
    }

    return <div
           style={{backgroundColor: 'hotpink', width: '10rem', height: '10rem' }}
           onClick={() => bar()}/>
}

et ce

const Parent = () => {
    [modalOpen, setModal] = React.useState(false);

    return <Child
               open={modalOpen}
               closeModal={() => setModal(false)}
               functionFromParent={() => console.log('Logged')} />
}

.

décide si le (c'est un Modal ) affiché ou non. a trois fonctions, closeModal () et functionFromParent () , provenant du code >. Et functionFromStore () provenant de redux via dispatchToProps () . Par souci de simplicité, j'ai laissé tous les trucs connect (stateToProps, dispatchToProps) (...) . Mais supposons que est directement connecté au store .

Cliquer sur

dans exécute bar () . Cela entraîne à démonter , car closeModal () dans le est appelé, fermeture du modal . Cependant, bar () appelle également foo () , étant une fonction async .

Lorsque le wait est résolu, le functionFromStore () est appelé, mais pas le functionFromParent () . Je me demande pourquoi ça? Pourquoi une fonction provenant du store est-elle appelée, même lorsque le composant ( ) est démonté, mais pas la fonction provenant du parent?

De plus, existe-t-il un moyen d'appeler functionFromParent () , même lorsque est démonté? D'une manière ou d'une autre, cela fonctionne avec functionFromStore () , y a-t-il un moyen de le faire fonctionner avec functionFromParent()?


5 commentaires

this.props dans le composant de fonction?


@marzelin Merci de l'avoir signalé. Je l'ai corrigé.


y a-t-il un moyen d'appeler functionFromParent (), même lorsque est démonté? Oui, pas besoin de changer quoi que ce soit J'ai ajouté une réponse indiquant que votre code fonctionne déjà. Si ce n'est pas le cas, c'est à cause de quelque chose que vous n'avez pas publié dans votre question. Pouvez-vous publier un code illustrant le problème?


Est-il possible que functionFromStore entraîne une erreur et, comme il s'agit d'une fonction asynchrone, il en résultera une promesse rejetée. La console Chrome peut vous dire si vous avez une promesse non tenue ou peut-être enregistrer quelque chose dans la capture?


@HMR Non, il n'y a pas d'erreur. Je peux aussi déplacer le functionFromParent () vers le bloc error {...} , même comportement.


3 Réponses :


-1
votes
function Child(props) {
  useEffect(() => {
    return () => {
      props.functionFromStore();
      props.functionFromParent();
    };
  });

  return (
    <div
      style={{ backgroundColor: "hotpink", width: "10rem", height: "10rem" }}
      onClick={props.closeModal}
    />
  );
}

1 commentaires

Je veux que les fonctions soient appelées dans la fonction async , car cela réagit aux erreurs résolues et . Dans useEffect () je ne peux pas faire la distinction entre les deux.



1
votes

9 commentaires

Vous ne pouvez pas reproduire car le ne se démonte pas "vraiment" dans votre code. Supposons que le est enveloppé dans un modal , material-ui.com/api/modal . Ensuite, le onClick = {bar} provoque le démontage du modal .


Désolé, je n'ai pas vu la condition que vous avez mise ici. Peut-être est-ce parce que le est ré-rendu plusieurs fois pendant que le async est appelé, provoquant functionFormParent () oubliez 'où il vient de '? Je ne sais pas comment exprimer cela, mais effectue un nouveau rendu plusieurs fois car il se passe des choses dans l'interface utilisateur pendant que l'appel asynchrone est effectué (Spinner, espace réservé affiché, ...) . C'est peut-être la raison pour laquelle est créé à nouveau, et functionFromParent () dans 'fait référence à' le ' old ' , celui avant le nouveau rendu?


@Stophface que fait vraiment functionFromParent ? Modifie l'état du parent? Autre chose?


Cela change l'état. functionFromParent = {foo => setState ({... state, [foo]: true})}


Et c'est l'état const [state, setState] = useState ({modalOpen: false, [foo]: false, [bar]: false,});


si [foo]: true un autre Composant est rendu dans


@Stophface obtenez-vous des erreurs dans la console concernant l'utilisation de setState sur un composant non monté?


C'est tout ... Merde. Cela a coûté du temps. Merci d'être resté avec moi!


@Stophface Pas de problème, j'aurais dû deviner que cela avait quelque chose à voir avec cela car cela provoque beaucoup de résultats inattendus.



1
votes

functionFromParent doit avoir été appelé. Il doit y avoir autre chose qui cause le problème.

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
const Parent = () => {
  const [showChild, setShowChild] = React.useState(true);
  const childProps = {
    fnFromParent: () => {
      console.log("logging from fnFromParent");
    },
    unmount: () => {
      setShowChild(false);
    }
  };
  return (
    <div>
      <p>I'm a Parent</p>
      { showChild &&
        <Child {...childProps} />
      }
    </div>
  );
};

const Child = ({ fnFromParent, unmount }) => {
  const delayed = () => {
    const p = new Promise(res => setTimeout(res, 3000))
    p.then(() => fnFromParent());
  };
  const clickHandler = () => {
    delayed();
    unmount();
  };
  return <p onClick={clickHandler}>I'm a Child (click to remove me)</p>;
};

ReactDOM.render(<Parent />, document.getElementById("root"));


1 commentaires

Merci pour votre réponse, mais nous avons déjà établi que , il se peut que le parent soit démonté et remonté donc l'état dans Parent est réinitialiser.