I'm trying to implement WebSocket support into my app by following React Native's own tutorial at https://reactnative.dev/docs/network#websocket-support.
Here is my code:
function initializeSocket(socket:WebSocket){
socket.onopen = () => {
store.dispatch(toggleWebsocketConnected(true));
};
socket.onclose = () => {
store.dispatch(toggleWebsocketConnected(false));
};
socket.onerror = (e:any) => {
console.log('websocket error', e);
store.dispatch(toggleWebsocketConnected(false));
};
socket.onmessage = (e) => {
processMessage(e);
};
}
In onerror
event handler (for now, ignore why error handler is called, this is not a "why can't I connect" question, but a TypeScript question) when it's triggered I'm getting a weird error at runtime:
TypeError [ERR_INVALID_THIS]: Value of "this" must be of type Event
at new NodeError (/path/to/my/project/lib/internal/errors.js:371:5)
at Event.[nodejs.util.inspect.custom] (/path/to/my/project/lib/internal/event_target.js:120:13)
at formatValue (/path/to/my/project/lib/internal/util/inspect.js:763:19)
at inspect (/path/to/my/project/lib/internal/util/inspect.js:340:10)
at formatWithOptionsInternal (/path/to/my/project/lib/internal/util/inspect.js:2006:40)
at formatWithOptions (/path/to/my/project/lib/internal/util/inspect.js:1888:10)
at console.value (/path/to/my/project/lib/internal/console/constructor.js:323:14)
at console.log (/path/to/my/project/lib/internal/console/constructor.js:359:61)
at EventTarget.socket.onerror (/path/to/my/project/src/services/myproject/socket.ts:27:17)
at EventTarget.dispatchEvent (/path/to/my/project/.vscode/.react/index.bundle:31193:27) {code: 'ERR_INVALID_THIS', stack: 'TypeError [ERR_INVALID_THIS]: Value of "this"…/myproject/.vscode/.react/index.bundle:31193:27)', message: 'Value of "this" must be of type Event', toString: Æ’, Symbol(kIsNodeError): true}
Vscode linter shows everything is fine though. When I hover over the onerror
function it shows:
(property) WebSocket.onerror: ((this: WebSocket, ev: Event) => any) | null
Two input arguments. So eventhough Vscode isn't complaining about my initial code, I also tried to change it to the following:
socket.onerror = (_:any, e:any) => {
console.log('websocket error', e);
store.dispatch(toggleWebsocketConnected(false));
};
Now, Vscode linter shows an error:
Type '(_: any, e: any) => void' is not assignable to type '(this: WebSocket, ev: Event) => any'.ts(2322)
If I run the code regardless of the error, I don't get a runtime error, yet _
is now an actual event object and e
is undefined:
What am I doing wrong? What is the correct form of doing it? I've stumbled upon a weird problem with this
keyword in arguments and TypeScript before (see Why are rest parameters undefined in TypeScript?) which indeed turned to be a Babel bug, which is now merged and fixed long ago.
How can I get it to work correectly?
UPDATE: I've managed to "work around" by turning the arrow function into a function with a function keyword:
socket.onerror = function(this:any, e:Event){
console.log('websocket error', e);
store.dispatch(toggleWebsocketConnected(false));
};
It "works" now, though this is not an actual solution as I still can't use arrow functions, breaking my code style as I never use function keyword
functions in code (other than top-level simple definitions) anywhere in the app.
No it doesn't, it seemed to step correctly yet actually threw an error again when I reached a line to console.log
the event.
from
React Native TypeScript WebSocket onerror Value of "this" must be of type Event