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
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()
?
3 Réponses :
function Child(props) { useEffect(() => { return () => { props.functionFromStore(); props.functionFromParent(); }; }); return ( <div style={{ backgroundColor: "hotpink", width: "10rem", height: "10rem" }} onClick={props.closeModal} /> ); }
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.
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.
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"));
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.
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 blocerror {...}
, même comportement.