I have this
const Parent = () => {
[modalOpen, setModal] = React.useState(false);
return <Child
open={modalOpen}
closeModal={() => setModal(false)}
functionFromParent={() => console.log('Logged')} />
}
and that
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()}/>
}
component.
<Parent />
decides if the <Child />
(it is a Modal ) shown or not. <Child />
has three functions, closeModal()
and functionFromParent()
, coming from the <Parent/ >
. And functionFromStore()
coming from redux
through dispatchToProps()
. For the sake of simplicity I left all the connect(stateToProps, dispatchToProps)(...)
stuff out. But lets assume <Child />
is directly connected to the store
.
Clicking on the <div />
in <Child/>
executes bar()
. That causes <Child />
to unmount
, because closeModal()
in the <Parent />
is called, closing the modal . However, bar()
also calls foo()
, being a async
function.
When the await
is resolved, the functionFromStore()
is called, but not the functionFromParent()
. I wonder why is that? Why is a function coming from the store
called, even when the component ( <Child />
) is unmounted, but not the function coming from the parent?
Further, is there a way to call functionFromParent()
, even when <Child />
is unmounted? Somehow it works with functionFromStore()
, is there a way to make it work with functionFromParent()
?
I cannot reproduce the behavior you describe but it's probably a closure problem as you're setting the state multiple times but have a stale state value in the closure of your handlers
You can solve it by passing a callback to the state setter: setSomeState(currentState=>({...currentState,changes}))
, here is a full example:
function Parent() { const [state, setState] = React.useState({ showModal: true, showFoo: false, }); return ( <div> {state.showModal? ( <Child open={state.showModal} closeModal={() => setState(state => ({...state, showModal: false, })) } functionFromParent={() => setState(state => ({...state, showFoo: true, })) } /> ): ( 'Child is gone ' )} {state.showFoo? <Foo />: 'no foo'} </div> ); } function Child({ functionFromParent, closeModal }) { function foo() { setTimeout(() => { functionFromParent(); }, 1000); } const bar = () => { foo(); closeModal(); }; return <button onClick={bar}>click me</button>; } function Foo() { return 'hi, I am Foo'; } ReactDOM.render( <Parent />, document.getElementById('root') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>
functionFromParent
must have been called. There must be something else that causing the problem.
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"));
<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>
function Parent() {
const [modalOpen, setModal] = React.useState(false);
return (
<Child
open={modalOpen}
closeModal={() => setModal(false)}
functionFromParent={() => console.log("Logged")}
/>
);
}
is there a way to call functionFromParent(), even when is unmounted? Somehow it works with functionFromStore(), is there a way to make it work with functionFromParent()?
useEffect
. You can see the code below, once you click your div , props.closeModal is invoked, which will unmount your Child component. Once the component unmount, useEffect
then performs a clean up which is in the return
block of the useEffect, which calls your functionFromParent
and functionFromStore
.function Child(props) {
useEffect(() => {
return () => {
props.functionFromStore();
props.functionFromParent();
};
});
return (
<div
style={{ backgroundColor: "hotpink", width: "10rem", height: "10rem" }}
onClick={props.closeModal}
/>
);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.