我正在尝试制作一个组件来呈现订单。我在 React 上使用 MVVN 架构。与后端的连接基于websocket连接。当我测试后端 webscoket 连接时,我能够得到响应。但在我的前端,我只看到发送的消息,但没有回复。我认为我处理 useEffect 的方式是错误的。但我不知道在哪里。
这是前端代码:
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 }
}
要解决 React 组件发送 WebSocket 消息但未收到响应的问题,请仔细检查 WebSocket 连接的 useEffect 处理: WebSocket 初始化:在 useEffect 中,确保使用正确的 URL 初始化 WebSocket,并且正确处理 onopen、onmessage、onerror 和 onclose 等所有事件。 onMessage 处理:确保您在 onmessage 事件中正确接收和处理消息。通常,后端响应是JSON格式的,因此解析event.data 清理WebSocket连接:确保在清理函数中正确关闭WebSocket,以防止内存泄漏。 检查后端响应:确保后端正确发送对 WebSocket 消息的响应。