Итак, у меня эта странная ошибка, и мне понадобится помощь, чтобы определить, откуда она вообще.
Чтобы лучше проиллюстрировать ошибку, я сделал скринкаст, который вы можете найти здесь: https://www.youtube.com/watch?v=MuXOfbYB_CI
Описание. На видео вы можете увидеть, как я использую свое приложение для подсчета очков, где левое окно - это контроллер для ввода бросков, а правое окно - это табло. После запуска игровые сайты будут перенаправлены на контроллер и табло через веб-сокеты. Итак, в следующий раз я заканчиваю игру, нажимая соответствующую кнопку, и сразу же начинаю новую игру таким же образом. При последующем вводе первого броска через контроллер возникнет ошибка.
Оба сайта (контроллер и табло выдают эту ошибку):
QueryData.ts:445 Uncaught TypeError: Cannot read property 'refetch' of undefined
at QueryData._this.obsRefetch (QueryData.ts:445)
at Socket.<anonymous> (ControllerPage.jsx:24)
at Socket.push../node_modules/socket.io-client/node_modules/component-emitter/index.js.Emitter.emit (index.js:133)
at Socket.push../node_modules/socket.io-client/lib/socket.js.Socket.onevent (socket.js:278)
at Socket.push../node_modules/socket.io-client/lib/socket.js.Socket.onpacket (socket.js:236)
at Manager.<anonymous> (index.js:21)
at Manager.push../node_modules/socket.io-client/node_modules/component-emitter/index.js.Emitter.emit (index.js:133)
at Manager.push../node_modules/socket.io-client/lib/manager.js.Manager.ondecoded (manager.js:345)
at Decoder.<anonymous> (index.js:21)
at Decoder.push../node_modules/socket.io-parser/node_modules/component-emitter/index.js.Emitter.emit (index.js:133)
at Decoder.push../node_modules/socket.io-parser/index.js.Decoder.add (index.js:251)
at Manager.push../node_modules/socket.io-client/lib/manager.js.Manager.ondata (manager.js:335)
at Socket.<anonymous> (index.js:21)
at Socket.push../node_modules/component-emitter/index.js.Emitter.emit (index.js:145)
at Socket.push../node_modules/engine.io-client/lib/socket.js.Socket.onPacket (socket.js:461)
at WS.<anonymous> (socket.js:278)
at WS.push../node_modules/component-emitter/index.js.Emitter.emit (index.js:145)
at WS.push../node_modules/engine.io-client/lib/transport.js.Transport.onPacket (transport.js:149)
at WS.push../node_modules/engine.io-client/lib/transport.js.Transport.onData (transport.js:141)
at WebSocket.ws.onmessage (websocket.js:160)
QueryData._this.obsRefetch @ QueryData.ts:445
(anonymous) @ ControllerPage.jsx:24
push../node_modules/socket.io-client/node_modules/component-emitter/index.js.Emitter.emit @ index.js:133
push../node_modules/socket.io-client/lib/socket.js.Socket.onevent @ socket.js:278
push../node_modules/socket.io-client/lib/socket.js.Socket.onpacket @ socket.js:236
(anonymous) @ index.js:21
push../node_modules/socket.io-client/node_modules/component-emitter/index.js.Emitter.emit @ index.js:133
push../node_modules/socket.io-client/lib/manager.js.Manager.ondecoded @ manager.js:345
(anonymous) @ index.js:21
push../node_modules/socket.io-parser/node_modules/component-emitter/index.js.Emitter.emit @ index.js:133
push../node_modules/socket.io-parser/index.js.Decoder.add @ index.js:251
push../node_modules/socket.io-client/lib/manager.js.Manager.ondata @ manager.js:335
(anonymous) @ index.js:21
push../node_modules/component-emitter/index.js.Emitter.emit @ index.js:145
push../node_modules/engine.io-client/lib/socket.js.Socket.onPacket @ socket.js:461
(anonymous) @ socket.js:278
push../node_modules/component-emitter/index.js.Emitter.emit @ index.js:145
push../node_modules/engine.io-client/lib/transport.js.Transport.onPacket @ transport.js:149
push../node_modules/engine.io-client/lib/transport.js.Transport.onData @ transport.js:141
ws.onmessage @ websocket.js:160
Рассматриваемая часть кода выглядит следующим образом:
const ControllerPage = () => {
const { loading, error, data, refetch } = useQuery(queries.GET_ALL_GAMES);
const [redirect, setRedirect] = useState(false);
useEffect(() => {
socket.on('redirect', (data) => {
if (data['target'] === 'controller') {
setRedirect(true);
}
});
socket.on('updateScoreboard', () => {
refetch();
});
}, [refetch]);
if (loading) return <div>Loading</div>;
if (error) throw error;
.... jada jada ...
render (
)
and so on
Как видите, я использую метод refetch, чтобы снова вручную запустить запрос в определении useQuery. Поэтому каждый раз, когда я ввожу бросок (вызов API throw / number / modifier), api будет возвращать socket.emit('updateScoreboard')
после обработки throw, а затем табло и контроллер извлекают последние данные, чтобы отразить изменения.
Но как вы можно увидеть по ошибке, покинув сторону один раз и вернувшись к ней, метода refetch как-то не будет. Как я могу предотвратить эту ошибку.
Когда я затем после короткого ожидания нажимаю Enter в обеих адресных строках браузера windows, и сайты перезагружаются, все снова будет в порядке и будет работать как задумано. Поскольку эта система должна работать в режиме киоска позже, обновление страницы, тем не менее, не является хорошим решением.
Любые инструкции будут высоко оценены
Решение
@ luke-dunscombe было совершенно правильным.
updateScoreboard нужно очистить. выбор return () => socket.disconnect
в качестве метода очистки не сработает, потому что сокет перестанет работать должным образом, но изменение этого помогло:
const ControllerPage = () => {
const { loading, error, data, refetch } = useQuery(queries.GET_ALL_GAMES);
const [redirect, setRedirect] = useState(false);
useEffect(() => {
socket.on('redirect', (data) => {
if (data['target'] === 'controller') {
setRedirect(true);
}
});
socket.on('updateScoreboard', () => {
refetch();
});
return () => socket.off('updateScoreboard');
}, [refetch]);
if (loading) return <div>Loading</div>;
if (error) throw error;
При возврате из хука useEffect я очистил его, перестав слушать updateScoreboard событие, которое отлично сработало.
Еще раз спасибо @ luke-dunscombe за правильную подсказку и ресурс.