I have created a sharedWorker using this script
// sharedWorker.js
importScripts('https://cdn.socket.io/4.3.1/socket.io.min.js');
let socket
let browserInstances = []
let counter = 0
onconnect = function(e) {
const port = e.ports[0]
browserInstances.push(port)
if (!socket) {
socket = io('socket-url');
socket.on('message', (message) => {
const msg = JSON.parse(message)
browserInstances.map(instance => {
instance.postMessage({type: msg.type, data: msg.data});
});
});
}
}
i am receiving two types of messages from socket one is {type: 'notification', data: '12345'} and the other is {type: 'event', data: '12345'}
now there are two listeners one is my main App.tsx component and the other is in my child component.
this is my App.tsx listener
worker.port.onmessage = (event: any) => {
console.log(event.data)
if (event.data.type === 'notification') {
console.log('Notification received:', event.data.data);
// Handle notification logic here
}
// Do not consume the message, let it propagate to other components
return true;
}
and this is my childComponent.tsx listener
worker.port.onmessage = (event: any) => {
console.log(event)
if (event.data.type === 'event') {
console.log('Event received:', event.data.data);
// Handle event logic here
}
}
And here is my WorkerContext.tsx code where i start the worker
// WorkerContext.ts
import React, { createContext, useEffect, useState, ReactNode } from 'react';
export const WorkerContext = createContext<any | undefined>(undefined);
interface WorkerProviderProps {
children: ReactNode;
}
export const WorkerProvider: React.FC<WorkerProviderProps> = ({ children }) => {
const [worker, setWorker] = useState<SharedWorker | null>(null);
useEffect(() => {
const sharedWorker = new SharedWorker('/sharedWorker.js');
setWorker(sharedWorker);
return () => {
sharedWorker.port.close();
};
}, []);
return (
<WorkerContext.Provider value={{ worker }}>
{children}
</WorkerContext.Provider>
);
};
Issue is that it is only receiving messages in App.tsx component, messages are not getting passed to childComponent.tsx but when i remove the App.tsx listener it gets passed to childComponent. How can i pass the message to App and childComponent based on data type?
worker.port.onmessage = ___
assigns to the onmessage
property, overwriting whatever value it had before (thus removing any previous event listener set up that same way). Instead, use worker.port.addEventListener("message", ___);
, so you can have multiple listeners for the event. See the EventTarget
docs for addEventListener
(MessagePort
is a subclass of EventTarget
). You also need to call start()
on the port (the onmessage
setter does that for you).