вызов асинхронной функции для родительского компонента - PullRequest
1 голос
/ 26 октября 2019

У меня есть этот

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 /> (это Модал ) показан или нет. <Child /> имеет три функции, closeModal() и functionFromParent(), исходя из <Parent/ >. И functionFromStore() идет от redux до dispatchToProps(). Ради простоты я оставил все вещи connect(stateToProps, dispatchToProps)(...). Но давайте предположим, что <Child /> напрямую связан с store.

Нажатие на <div /> в <Child/> выполняет bar(). Это вызывает от <Child /> до unmount, потому что closeModal() в <Parent /> вызывается, закрывая модальный . Однако bar() также вызывает foo(), являясь async функцией.

Когда разрешен await, вызывается functionFromStore(), но не functionFromParent(). Интересно, почему это? Почему вызывается функция из store, даже если компонент (<Child />) размонтирован, а функция не из родительского?

Кроме того, есть ли способ вызвать functionFromParent(), даже когда <Child /> размонтирован? Как-то работает с functionFromStore(), есть ли способ заставить его работать с functionFromParent()?

Ответы [ 3 ]

1 голос
/ 26 октября 2019

Я не могу воспроизвести описанное вами поведение, но, вероятно, это проблема закрытия , так как вы устанавливаете состояние несколько раз, но у вас есть устаревшее значение состояния при закрытии ваших обработчиков

Выможно решить, передав обратный вызов установщику состояния: 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>
1 голос
/ 26 октября 2019

functionFromParent должен быть вызван. Должно быть что-то еще, что вызывает проблему.

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>
0 голосов
/ 26 октября 2019
function Parent() {
  const [modalOpen, setModal] = React.useState(false);

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

есть ли способ вызвать functionFromParent (), даже если он отключен? Каким-то образом это работает с functionFromStore (), есть ли способ заставить его работать с functionFromParent ()?

  • Да! Когда ваш компонент размонтируется, вы можете выполнитьочистка, которую обеспечивают React hooks 'useEffect. Вы можете увидеть код ниже, как только вы нажмете div , props.closeModal , который размонтирует ваш Child компонент. После размонтирования компонента useEffect выполняет очистку, которая находится в блоке return объекта useEffect, который вызывает ваши functionFromParent и functionFromStore.
function Child(props) {
  useEffect(() => {
    return () => {
      props.functionFromStore();
      props.functionFromParent();
    };
  });

  return (
    <div
      style={{ backgroundColor: "hotpink", width: "10rem", height: "10rem" }}
      onClick={props.closeModal}
    />
  );
}
.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...