Как помнить, что компонент React-хуков отключен, поэтому можно избежать изменений состояния? - PullRequest
1 голос
/ 27 мая 2019

Со старым кодом React.js, основанным на классах, я могу сделать так, чтобы помнить, что компонент был размонтирован:

  componentWillUnmount: function() {
    this.isGone = true;
  },

  loadUsers: function() {
    Server.loadUsers(..., (response) => {
      if (this.isGone) return;
      ...
    });
  }

Как можно сделать то же самое, на основе хуковкомпоненты?

Вот пример компонента функции перехвата, где я не уверен, как запомнить, что он был размонтирован, поэтому я могу return перед вызовом любого setSomeState:

export const GroupMembers = React.createFactory(function(props) {

  const [membersOrNull, setMembers] = React.useState(null);
  let isGone = false;  // ? (se [222] below

  React.useEffect(() => {
    Server.listGroupMembers(someGroupId, (response) => {
     if (/* is unmounted ?? */) return;
     setMembers(response.members);
    });
    return () => { /* how remember is unmounted?
                      would isGone = true; work? */ };
  }, []);

  ...

  return ..., Button({ title: "Remove all members", onClick: () => {
    Server.removeAllMembers(someGroupId, () => {
     if (/* is unmounted ?? */) return;
     setMembers([]);
    });
  }});

Я полагаю, что я не могу использовать const [isGone, setGone] = useState(false), потому что я не должен пытаться получить доступ к состоянию (прочитайте isGone) после того, как был размонтирован.И если я [222] добавлю локальный let isGone = false внутри функции, мне кажется, что различные обратные вызовы, созданные внутри функции, будут ссылаться на разные «экземпляры» этой локальной переменной, в зависимости от того, в какойдругой GroupMembers(..) вызов различных обратных вызовов были созданы?или я ошибаюсь и это работает?- Может быть, я мог бы создать внешнюю функцию-обертку с локальным let isGone = false, однако это добавляет еще одну функцию обертки и отступ: - /

Ответы [ 2 ]

1 голос
/ 27 мая 2019

Поскольку вы используете флаг isGone вне метода useEffect, вы можете использовать useRef для хранения таких переменных, как

export const GroupMembers = React.createFactory(function(props) {

  const [membersOrNull, setMembers] = React.useState(null);
  const isGone = useRef(false);  // ? (se [222] below

  React.useEffect(() => {
    Server.listGroupMembers(someGroupId, (response) => {
     if (isGone.current) return;
     setMembers(response.members);
    });
    return () => { 
       isGone.current = true;
    };
  }, []);

  ...

  return ..., Button({ title: "Remove all members", onClick: () => {
    Server.removeAllMembers(someGroupId, () => {
     if (isGone.current) return;
     setMembers([]);
    });
  }});

PS: лучший способ справиться с такими вещами - отменить запрос, когда Вы покидаете страницу, а не ждете ответа только пренебрегать им.

1 голос
/ 27 мая 2019

просто используйте локальную переменную, доступную через замыкание

React.useEffect(() => {
  let isActual = true;
  Server.listGroupMembers(someGroupId, (response) => {
     if (!isActual) return;
     setMembers(response.members);
  });
  return () => {isActual = false;};
}, []);

в этом случае флаг будет обновляться только при размонтировании. но в общем случае (с некоторыми зависимостями от безработицы для useEffect) он также будет использоваться. Так что в случае последовательного рендеринга вы можете быть уверены, что никогда не обработаете более старый запрос.

PS Самый универсальный способ - отменить запрос, когда это возможно.

...