1

I have a barchart made with chartjs in a React app. It works well, but the data parsing could be handled by a web worker so as to speed up the page loading.

I have declared my web worker in a useEffect function:

  let data = React.useRef([]);

  useEffect(() => {
    const dataWorker: Worker = new Worker("./worker.ts");
    dataWorker.postMessage({
      msg: "formatData",
      data: { series, theme, range },
    });
    dataWorker.onmessage = (e: MessageEvent) => {
      if (e && e.data) {
        data.current = e.data;
      }
    };
  }, [range, series, theme]);

And the webworker is defined in a separate file worker.ts:

self.onmessage = async (e) => {
  if (e && e.data && e.data.msg === "formatData") {
    const { sortedSeries, theme, range } = e.data;
    // eslint-disable-next-line react-hooks/rules-of-hooks
    const data = useFormatData(sortedSeries, theme, range);
    self.postMessage(data);
  }
};

function useFormatData(series, theme, range) {
  return useMemo(() => {
   // do stuff
    };
  }, [range, sortedSeries, theme]);
}

The worker makes the page crash with the following error:

Uncaught DOMException: Failed to execute 'postMessage' on 'Worker: function (number) { var b = number % 10, output = toInt((number...... } could not be cloned.

How to fix this?

DoneDeal0
  • 5,273
  • 13
  • 55
  • 114

1 Answers1

1

I recently saw this issue when I was passing an object to the web worker that contained a function that I was not aware of.

By the looks of your error, it could be the case for you as well in regards to series, theme, or range being passed to the worker.

There is a good explanation of alternatives explained in this SO Answer. To summarize, it mentions passing only the the serializable data to the worker and then adding back the functions (if necessary) on the webworker side.

rdrw
  • 763
  • 1
  • 8
  • 17