Skip to content

Instantly share code, notes, and snippets.

@msociety
Created August 21, 2020 10:49
Show Gist options
  • Save msociety/71dd2ccd2c25118571893875a363d8e2 to your computer and use it in GitHub Desktop.
Save msociety/71dd2ccd2c25118571893875a363d8e2 to your computer and use it in GitHub Desktop.
web worker
import { cookData } from './helpers/someFunction';
onmessage = ({ data: [...args] }) => {
const cookedData = cookData(...args);
postMessage(cookedData);
};
// ---------- ComponentX.js ------------
import React, { useMemo } from 'react';
...
/* eslint-disable-next-line import/no-webpack-loader-syntax */
import CookDataWorker from 'worker-loader!./cookData.worker';
const cookDataWorker = new CookDataWorker();
const ComponentX = () => {
...
const workerInput = useMemo(() => [arg1, arg2], [arg1, arg2]);
const { result: cookedData } = useWorker(cookDataWorker, workerInput);
...
// ---------- useWorker.js ------------
import { useEffect, useRef, useReducer } from 'react';
// * This hook is based in react-hooks-worker's useWorker
const defaultState = { result: null, error: null };
const reducer = (state, { type, payload }) => {
switch (type) {
case 'reset':
return defaultState;
case 'message':
return { result: payload, error: null };
case 'error':
return { result: null, error: 'error' };
case 'messageerror':
return { result: null, error: 'messageerror' };
default:
throw new Error('no such action type');
}
};
/**
* @param worker: instanceof Worker
*/
const useWorker = (worker, input) => {
const [state, dispatch] = useReducer(reducer, defaultState);
const prevWorker = useRef(null);
useEffect(() => {
prevWorker.current = worker;
let dispatchSafe = action => dispatch(action);
/* eslint-disable no-param-reassign */
worker.onmessage = e => dispatchSafe({ type: 'message', payload: e.data });
worker.onerror = () => dispatchSafe({ type: 'error' });
worker.onmessageerror = () => dispatchSafe({ type: 'messageerror' });
/* eslint-enable no-param-reassign */
return () => {
dispatchSafe = () => null;
worker.terminate();
dispatch({ type: 'reset' });
};
}, [worker]);
useEffect(() => {
prevWorker.current.postMessage(input);
}, [input]);
return state;
};
export default useWorker;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment