简体   繁体   English

异步 Function 调用父组件

[英]async Function call to Parent Component

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. <Parent />决定是否显示<Child /> (它是Modal )。 <Child /> has three functions, closeModal() and functionFromParent() , coming from the <Parent/ > . <Child />具有三个函数, closeModal()functionFromParent() ,来自<Parent/ > And functionFromStore() coming from redux through dispatchToProps() .并且functionFromStore()来自redux通过dispatchToProps() For the sake of simplicity I left all the connect(stateToProps, dispatchToProps)(...) stuff out.为了简单起见,我留下了所有的connect(stateToProps, dispatchToProps)(...)东西。 But lets assume <Child /> is directly connected to the store .但是让我们假设<Child />直接连接到store

Clicking on the <div /> in <Child/> executes bar() .单击<Child/>中的<div /> > 会执行bar() That causes <Child /> to unmount , because closeModal() in the <Parent /> is called, closing the modal .这会导致<Child /> unmount ,因为调用了<Parent />中的closeModal() ,从而关闭了modal However, bar() also calls foo() , being a async function.但是, bar()也调用foo() ,作为async function。

When the await is resolved, the functionFromStore() is called, but not the functionFromParent() .await解决时,调用functionFromStore() ,但不调用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?为什么来自store的 function 被调用,即使组件( <Child /> )已卸载,但不是来自父级的 function ?

Further, is there a way to call functionFromParent() , even when <Child /> is unmounted?此外,有没有办法调用functionFromParent() ,即使<Child />已卸载? Somehow it works with functionFromStore() , is there a way to make it work with functionFromParent() ?它以某种方式与functionFromStore()一起工作,有没有办法让它与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我无法重现您描述的行为,但这可能是一个关闭问题,因为您多次设置 state 但在处理程序的关闭中有一个陈旧的 state 值

You can solve it by passing a callback to the state setter: setSomeState(currentState=>({...currentState,changes})) , here is a full example:您可以通过将回调传递给 state 设置器来解决它: setSomeState(currentState=>({...currentState,changes})) ,这是一个完整的示例:

 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. functionFromParent必须已被调用。 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?有没有办法调用 functionFromParent(),即使在卸载时? Somehow it works with functionFromStore(), is there a way to make it work with functionFromParent()?它以某种方式与 functionFromStore() 一起工作,有没有办法让它与 functionFromParent() 一起工作?

  • Yes!是的! When your component unmount, you can perform a cleanup which is provided by React hooks' useEffect .当你的组件卸载时,你可以执行由 React 钩子的useEffect提供的清理。 You can see the code below, once you click your div , props.closeModal is invoked, which will unmount your Child component.您可以看到下面的代码,一旦您单击div ,就会调用props.closeModal ,这将卸载您的Child组件。 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 .一旦组件卸载, useEffect然后执行清理,它位于 useEffect 的return块中,它调用您的functionFromParentfunctionFromStore
function Child(props) {
  useEffect(() => {
    return () => {
      props.functionFromStore();
      props.functionFromParent();
    };
  });

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM