S
SolidJS•14mo ago
akerbeltz

Websockets on Solidjs

I have some code in React for websocket conexion in components, I tried to port the code to solidjs, but no success yet.
// Websockets
onMount(() => {
const initWebSocket = () => {
let hostname = window.location.hostname;
console.log(hostname);
if (hostname === "localhost") ws = new WebSocket("ws://localhost:5000/");
else ws = new WebSocket("ws://" + hostname + "/api/events/ws");

console.log(ws);
ws.onclose = onClose;
ws.onmessage = onMessage;
ws.onerror = onError;
};

const onClose = (e) => {
setTimeout(initWebSocket, 2000);
};

const onError = (event) => {
console.error("Error:" + event);
};

// Listener websocket message
//////////////////////////////////////////////////
const onMessage = (e) => {
console.log(e.data);
};
initWebSocket();
});
// Websockets
onMount(() => {
const initWebSocket = () => {
let hostname = window.location.hostname;
console.log(hostname);
if (hostname === "localhost") ws = new WebSocket("ws://localhost:5000/");
else ws = new WebSocket("ws://" + hostname + "/api/events/ws");

console.log(ws);
ws.onclose = onClose;
ws.onmessage = onMessage;
ws.onerror = onError;
};

const onClose = (e) => {
setTimeout(initWebSocket, 2000);
};

const onError = (event) => {
console.error("Error:" + event);
};

// Listener websocket message
//////////////////////////////////////////////////
const onMessage = (e) => {
console.log(e.data);
};
initWebSocket();
});
Any idea of how would look this to work correctly? the idea of the websockets is to update an http resource (I think I'll use the mutate of the createResource API)
19 Replies
Alex Lohr
Alex Lohr•14mo ago
A nice pattern to use is to put the message into a signal to use it inside an effect.
const hostname = location.hostname;
const sendQueue = [];
const [message, setMessage] = createSignal();
const ws = new WebSocket(
hostname === 'localhost'
? 'ws://localhost:5000'
: `ws://${hostname}/api/events/ws`
);

const send = (data) => {
ws.readyState == 1
? ws.send(data)
: sendQueue.push(data);
};
ws.addEventListener('message', ({ data }) => setMessage(data));
ws.addEventListener('open', () => {
while (sendQueue.length)
ws.send(sendQueue.shift());
});
return [message, send];
const hostname = location.hostname;
const sendQueue = [];
const [message, setMessage] = createSignal();
const ws = new WebSocket(
hostname === 'localhost'
? 'ws://localhost:5000'
: `ws://${hostname}/api/events/ws`
);

const send = (data) => {
ws.readyState == 1
? ws.send(data)
: sendQueue.push(data);
};
ws.addEventListener('message', ({ data }) => setMessage(data));
ws.addEventListener('open', () => {
while (sendQueue.length)
ws.send(sendQueue.shift());
});
return [message, send];
You can then use
createEffect(on(message, (data) => ..., { defer: true }));

<button onClick={() => send(...)}>send</button>
createEffect(on(message, (data) => ..., { defer: true }));

<button onClick={() => send(...)}>send</button>
akerbeltz
akerbeltz•14mo ago
Thanks. The idea is more to receive the updates via websockets of an initial get via http request. In that page the client don't get updates.
Alex Lohr
Alex Lohr•14mo ago
What's the protocol for the mutation? Are you using some sort of diffing?
akerbeltz
akerbeltz•14mo ago
I'm trying something like that
const onMessage = (e) => {
const dispatchMessage = (control) => {
let ref = (control.data.reference_value = 1);
console.log({ ...control, ref });
return { ...control, ref };
};
mutate((control) => dispatchMessage(control));
};
const onMessage = (e) => {
const dispatchMessage = (control) => {
let ref = (control.data.reference_value = 1);
console.log({ ...control, ref });
return { ...control, ref };
};
mutate((control) => dispatchMessage(control));
};
but this don't reflect the changes for some reason there's no reactivity with the component I mean The resource is updated correctly though

return (
{control().data.reference_value}
<DescriptionList
items={[
["Frequency Reference", control().data.reference_value],
]}
/>

return (
{control().data.reference_value}
<DescriptionList
items={[
["Frequency Reference", control().data.reference_value],
]}
/>
outside the component it renders correctly but inside the component no. I hope I explained that good. My bad, I was destructuring the component the react way 😅 . It's hard to get used to that part.
Alex Lohr
Alex Lohr•14mo ago
There's a babel plugin to fix this problem: https://github.com/orenelbaum/babel-plugin-solid-undestructure
GitHub
GitHub - orenelbaum/babel-plugin-solid-undestructure: A Babel plugi...
A Babel plugin for SolidJS that allows you to destructure component props without losing reactivity. - GitHub - orenelbaum/babel-plugin-solid-undestructure: A Babel plugin for SolidJS that allows y...
akerbeltz
akerbeltz•14mo ago
I'll check, thanks again!
DaOfficialWizard🧙
you can also use @solidjs-use which has an awesome WebSocket hook ready to go.
akerbeltz
akerbeltz•14mo ago
I looked into that and don't see the ws hook, how it's called?
DaOfficialWizard🧙
Go to their documentation website. The hook is called useWebSocket
akerbeltz
akerbeltz•14mo ago
npm
solid-use
A collection of SolidJS utilities. Latest version: 0.7.0, last published: 2 months ago. Start using solid-use in your project by running npm i solid-use. There are 9 other projects in the npm registry using solid-use.
akerbeltz
akerbeltz•14mo ago
Do you recomend using this as a global signal or with a context provider ? What i want to do is to do with the websockets is to update the initial resource of a get request. This will be done in the multiple childs nested on a parent in different nesting levels.
bigmistqke
bigmistqke•14mo ago
Unfortunate naming
akerbeltz
akerbeltz•14mo ago
I see.. it don't appear in the google search
DaOfficialWizard🧙
does for me @solidjs-use shows right up on npm
akerbeltz
akerbeltz•14mo ago
hmm strange @daofficialwizard Anyway the pattern that posted @lexlohr fits the needs of the project i think Idk if i would do a global signal or a provider but seems to work well
Alex Lohr
Alex Lohr•14mo ago
I should probably redo the WebSocket package for solid-primitives. I would probably expose the connection instance.
akerbeltz
akerbeltz•14mo ago
The api is so well documented. So nice to have the docs with a playground on the side and well structured in the tutorials cool
DaOfficialWizard🧙
sure, they provided a great suggestion 🙂