首页 > 解决方案 > 对父组件的异步函数调用

问题描述

我有这个

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

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

然后

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()}/>
}

零件。

<Parent />决定是否显示<Child />(它是Modal)。 <Child />具有三个功能,closeModal()functionFromParent(),来自<Parent/ >. 并且functionFromStore()来自redux通过dispatchToProps()。为了简单起见,我把所有的connect(stateToProps, dispatchToProps)(...)东西都省略了。但是让我们假设<Child />直接连接到store.

单击<div />in<Child/>执行bar()。这会导致<Child />unmount因为closeModal()<Parent />被调用时,关闭modal。但是,bar()也调用foo(), 作为一个async函数。

await解决后,将调用functionFromStore(),但不调用functionFromParent()。我想知道这是为什么?为什么一个函数来自被store调用,即使组件 ( <Child />) 已卸载,但不是来自父级的函数?

此外,有没有办法调用functionFromParent(),即使<Child />已卸载?它以某种方式工作functionFromStore(),有没有办法让它工作functionFromParent()

标签: javascriptreactjsreduxreact-redux

解决方案


我无法重现您描述的行为,但这可能是一个关闭问题,因为您多次设置状态但在处理程序的关闭中有一个陈旧的状态值

您可以通过将回调传递给 state setter: 来解决它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>


推荐阅读