Попытка использовать EventEmitter и useState одновременно. Что я делаю неправильно? - PullRequest
1 голос
/ 23 апреля 2020

Я немного новичок в ReactJS и все еще пытаюсь обернуться вокруг вещей. В настоящее время у меня проблемы с использованием EventEmitter при одновременном использовании useState.

Вот моя песочница: https://codesandbox.io/s/vibrant-germain-q4933

Если вы наблюдаете за консолью и нажимаете кнопки «emit» или «child emit», она работает нормально. Сигнал излучается и принимается. Однако, как только вы несколько раз нажмете кнопку «дочерний счет», а затем go назад и нажмете «дочерний выброс», вы увидите, что все начинает повторяться.

Эта проблема, по-видимому, возникает, только если вы используете useState и emitter.on в одном и том же дочернем элементе. Это, вероятно, связано с передачей излучателя в качестве опоры. Не уверен, что это хорошая идея или нет.

Чего мне здесь не хватает концептуально?

Спасибо

1 Ответ

0 голосов
/ 23 апреля 2020

Вы не должны определять свои экземпляры эмиттера непосредственно в цикле рендеринга функции. Вместо этого вы должны создавать и добавлять события списка только один раз.

Чтобы создать список только один раз, используйте useRef, а чтобы добавить список только один раз, используйте useEffect hook

Пример кода

const App = props => {
  const myEmitter = useRef(new EventEmitter());
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    myEmitter.current.on("event", msg => {
      console.log("Parent received: " + msg);
    });
  }, []);

  const Send = () => {
    myEmitter.current.emit("event", "parent sending this message.");
  };

  return (
    <Content>
      <button onClick={Send}>emit</button>
      <button onClick={() => setCounter(counter + 1)}>count {counter}</button>
      <Child myEmitter={myEmitter.current} />
    </Content>
  );
};

import React, { useState, useEffect } from "react";

const Child = props => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    props.myEmitter.on("event", msg => {
      console.log("Child received: " + msg);
    });
  }, [props.myEmitter]);

  const Emit = () => {
    props.myEmitter.emit("event", "child sending this message");
  };

  return (
    <>
      <button onClick={Emit}>child emit</button>
      <button onClick={() => setCounter(counter + 1)}>
        child count {counter}
      </button>
    </>
  );
};

export default Child;

Демо

...