Не удается закрыть сокет при выходе из системы

  const [socket, setSocket] = useState(null);
  useLayoutEffect(() => {
    auth().onAuthStateChanged(async (user) => {
      if (!!user) {
        props.login();
        const token = await user.getIdToken(true);
        setSocket(await getSocket(token, props.store));
      } else {
        console.log(socket); // return null when logout
        if (socket) socket.close();
        props.logout();
        setSocket(null);
      }
    });
  }, []);

Я создаю приложение React, использующее socket.io и firebase. Когда пользователь вошел в систему, я аутентифицирую и сохраняю сокет, когда я выхожу из системы, я хотел бы отключить сокет, но не могу. Сокет возвращает ноль, почему?


person Daniel Chan    schedule 20.05.2020    source источник
comment
Вы удостоверились, что ваш getSocket () возвращает ненулевые значения?   -  person AsifM    schedule 20.05.2020


Ответы (2)


Причина, по которой вы получаете значение null при выходе из системы, заключается в том, что ваш useLayoutEffect запускается только один раз, а значение сокета получается из закрытия, когда он запускается, который равен нулю

Вместо использования состояния для хранения сокета используйте ref

const socket = useRef(null);
  useLayoutEffect(() => {
    auth().onAuthStateChanged(async (user) => {
      if (!!user) {
        props.login();
        const token = await user.getIdToken(true);
        socket.current =await getSocket(token, props.store));
      } else {
        console.log(socket.current);
        if (socket.current) socket.current.close();
        props.logout();
        socket.current = null;
      }
    });
  }, []);
person Shubham Khatri    schedule 20.05.2020
comment
Получаете ли вы какую-нибудь ошибку? Также вы можете убедиться, что getSocket возвращает правильное значение сокета - person Shubham Khatri; 20.05.2020
comment
Это работает, теперь сокет не нулевой. Я раньше не использовал useRef, могу ли я узнать, когда уместно использовать useRef вместо useState, в чем их разница - person Daniel Chan; 20.05.2020
comment
обновления состояния связаны с закрытием, тогда как обновления ref работают с мутацией, вы можете использовать refs, когда хотите сохранить константные значения, которые не должны запускать повторную визуализацию, а также для решения проблем с закрытием. Состояние - это то, что вы используете, когда хотите запускать повторную визуализацию при изменении - person Shubham Khatri; 20.05.2020
comment
Итак, моя исходная проблема кода заключается в том, что функция обратного вызова содержит ссылку на значения переменных при создании, поэтому не реагирует на внешнее изменение. Для useRef он создает объект, его значение изменяется, чтобы ссылка на память могла получить обновленное значение. Я прав? - person Daniel Chan; 20.05.2020
comment
Возникает другая проблема, теперь я использую useRef вместо useState, повторный рендеринг не вызывается, но он мне нужен, так как сокет передается для использования другим компонентам; - person Daniel Chan; 20.05.2020
comment
Вы можете передать ссылку другому компоненту, это не будет проблемой. Для этого вам не нужен setState - person Shubham Khatri; 20.05.2020

const [socket, setSocket] = useState(null);    

  useLayoutEffect(() => {
    let socket;
    auth().onAuthStateChanged(async (user) => {
      if (!!user) {
        const token = await user.getIdToken(true);
        socket = await getSocket(token, props.store)
        setSocket(socket);
        props.login(socket);
      } else {
        if (socket) {socket.close();}
        socket = null;
        setSocket(null);
        props.logout();
        props.clearTodoList();
      }
    });
  }, []);

Спасибо за помощь Шубхаму Хатри, у меня возникла идея продолжать использовать useState, но решить проблему с закрытием.

person Daniel Chan    schedule 20.05.2020