I’m trying to make a component to render an order. I’m using MVVN architecture on React. The connection with backend is based on websocket connections. When I test the backend webscoket connection I am able to get the response. But on my frontend side, I only see the message sent, but no answer back. I think that the way that I am handling the useEffect is wrong. But I’m no sure where.
This is the frontend code:
import { useCallback, useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import useWebSocket, { ReadyState } from 'react-use-websocket'
import { UseCase } from '@/domain/model/types'
import { Epc, Order } from '@/domain/model/OrderTagging'
import { PrinterPoint, Terminal } from '@/domain/model/PrinterPoint'
import { ROUTES } from '@/utils/common/constant'
import { toaster } from '@/utils/common/toaster'
import { StorageKeys } from '@/utils/common/constant/storage'
import useStoreDataInLocalStorage from '@/hooks/useStoreDataInLocalStorage'
import { closeCodeMessages, WebSocketCloseCode } from './webSocketCloseCodes'
import { FormDataSchema } from '@/presenter/components/OrderForm/view-models/types'
type Dependencies = {
readonly getOrderUseCase: UseCase<Order>
}
export type UseOrderViewModelResponse = {
order: Order | null
queue: Epc[] | null
isLoading: boolean
sendMessageOnSubmit: (formData: FormDataSchema) => void
}
export const useOrderViewModel = ({ getOrderUseCase }: Dependencies): UseOrderViewModelResponse => {
const [order, setOrder] = useState<Order | null>(null)
const [queue] = useState<Epc[] | null>(null)
const [socketUrl, setSocketUrl] = useState<string | null>(null)
const [isLoading, setIsLoading] = useState(true)
const navigate = useNavigate()
const { value: locality } = useStoreDataInLocalStorage<PrinterPoint>(StorageKeys.User.Locality)
const { value: terminal } = useStoreDataInLocalStorage<Terminal>(StorageKeys.User.Terminal)
const { sendJsonMessage, lastJsonMessage, readyState } = useWebSocket(socketUrl, {
onOpen: () => {
// eslint-disable-next-line no-console
console.log('Open connection')
},
onMessage: (evt) => {
// eslint-disable-next-line no-console
console.log('Message received:', evt.data)
},
onClose: () => {
// eslint-disable-next-line no-console
console.log('Close connection')
},
onError: () => {
// eslint-disable-next-line no-console
console.log('Close onError')
},
shouldReconnect: (evt) => {
try {
const { message, isError } = handleWebSocketCloseCode(evt.code as WebSocketCloseCode)
toaster('error', message)
return isError
} catch (e) {
// eslint-disable-next-line no-console
console.log(e)
return false
}
},
reconnectInterval: 1500,
reconnectAttempts: 3
})
function handleWebSocketCloseCode(code: WebSocketCloseCode) {
const message = closeCodeMessages[code] || `Código de fechamento desconhecido: ${code}`
const isError = code !== 1000
return { message, isError }
}
const sendMessageOnSubmit = (formData: FormDataSchema) => {
sendJsonMessage({
action: 'start_print',
data: {
storeNumber: order?.storeNumber,
ean: formData.product,
quantity: formData.quantity,
expiryDate: formData.expiryDate,
productSession: formData.product
}
})
}
const getOrderData = useCallback(async () => {
try {
setIsLoading(true)
sendJsonMessage({
action: 'open_order',
data: {
boxBarcode: '00002919802331',
bureauIdentifier: 'cd_x',
storeNumber: '21955',
owner: 'user1',
terminalIdentifier: 'Bancada 01'
}
})
} catch (error) {
toaster('error', 'Erro ao carregar os dados do pedido. Por favor, tente novamente.')
navigate(`/${ROUTES.TABS}`)
} finally {
setIsLoading(false)
}
}, [])
useEffect(() => {
const controller = new AbortController()
if (locality?.identifier && terminal?.name) {
setSocketUrl(`${import.meta.env.VITE_SOCKET_CONNECT}/${locality.identifier}/${terminal.name}`)
}
;(async () => await getOrderData())()
return () => {
controller.abort()
}
}, [])
return { order, queue, isLoading, sendMessageOnSubmit }
}