timhaley94/holdem

View on GitHub
client/src/state/socket.js

Summary

Maintainability
A
0 mins
Test Coverage
F
0%
import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useState,
} from 'react';
import PropTypes from 'prop-types';
import io from 'socket.io-client';
import { useHistory } from 'react-router-dom';
import config from '../config';
import { useUser } from './user';

const Context = createContext(null);

function SocketProvider({ children }) {
  const { push } = useHistory();
  const [{ token }] = useUser();

  // Socket State
  const [_socket, setSocket] = useState(null);
  const [isConnected, setIsConnected] = useState(false);

  const reset = useCallback(() => {
    setIsConnected(false);
    setSocket(null);
  }, [setIsConnected, setSocket]);

  const fatal = useCallback(() => {
    // Log fatal here
    reset();
    push('/error');
  }, [reset, push]);

  useEffect(() => {
    if (token) {
      const socket = io(config.serverUrl, {
        query: { token },
        transports: ['websocket'],
      });

      socket.on('connect', () => setIsConnected(true));
      socket.on('connect_error', fatal);
      socket.on('connect_timeout', fatal);
      socket.on('error', fatal);
      socket.on('disconnect', reset);

      setSocket(socket);

      return () => {
        // Must be wrapped in anonymous function because
        // of 'this' binding inside .disconnect()
        socket.disconnect();
      };
    }
  }, [token, push, reset, fatal]);

  const value = {
    socket: (
      isConnected
        && _socket
        ? _socket
        : null
    ),
  };

  return (
    <Context.Provider value={value}>
      { children }
    </Context.Provider>
  );
}

SocketProvider.propTypes = {
  children: PropTypes.node.isRequired,
};

function useSocket() {
  return useContext(Context);
}

export {
  SocketProvider,
  useSocket,
};