// Create class to interact with sockets
import { io, Socket } from 'socket.io-client'
export default class SocketClient {
socket: Socket | null | undefined
connect() {
this.socket = io('https://localhost:8080', {
extraHeaders: {
Authorization: 'Bearer ...',
},
})
}
disconnect() {
if (this.socket) {
this.socket.disconnect()
this.socket = null
}
}
emit(eventName: string, data: any) {
if (this.socket) {
this.socket.emit(eventName, data)
}
}
on(eventName: string, func: () => void) {
if (this.socket) {
this.socket.on(eventName, func)
}
}
}
// -----------------------------------------------------
// When we create a store, we add middleware with socket
// -----------------------------------------------------
export const socket = new SocketClient()
export function makeStore() {
return configureStore({
// ...
middleware: [socketMiddleware(socket)],
})
}
// -----------------------------------------------------
// Track all dispatches and interact with the socket
// -----------------------------------------------------
import { Dispatch } from 'redux'
import { RootState } from 'stores/rootReducer'
// Here can be any dispatch to open a connection
const INIT_KEY = 'connect/socket'
interface SocketMiddlewareParams {
dispatch: Dispatch
getState: () => RootState
}
const socketMiddleware = (socket: any) => {
return (params: SocketMiddlewareParams) => (next: any) => (action: any) => {
const { dispatch } = params
const { type, payload } = action
if (type === INIT_KEY) {
socket.connect()
// Example ON
socket.on('user/connect', (socketIds: any) => {
socket.emit('sync', socketIds)
})
}
switch (type) {
// Example EMIT
case 'user/disconnect': {
socket.emit('joinRoom', payload.room)
break
}
default:
break
}
return next(action)
}
}
// Usage
import { useDispatch } from 'react-redux'
import { useEffect } from 'react'
function MyApp() {
const dispatch = useDispatch()
useEffect(() => {
dispatch({ type: 'socket/connect' })
}, [])
return (
<div> Yep! </div>
)
}