/redux-in-worker

Entire Redux in Web Worker

Primary LanguageTypeScriptMIT LicenseMIT

redux-in-worker

CI npm size discord

Entire Redux in Web Worker

Introduction

Inspired by React + Redux + Comlink = Off-main-thread.

This is still an experimental project. Please give us a feedback to make it stable.

Some key points are:

  • It only sends "diffs" from the worker thread to the main thread.
  • All Objects in a state tree keep the ref equality.
  • It can run middleware in the worker thread. (only non-DOM middleware #2)
  • No async functions are involved.
  • No proxies are involved.

Install

npm install redux-in-worker

Usage

store.worker.js:

import { createStore } from 'redux';
import { exposeStore } from 'redux-in-worker';

const initialState = { count: 0 };
const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + 1 };
    case 'decrement':
      return { ...state, count: state.count - 1 };
    default:
      return state;
  }
};

const store = createStore(reducer);

exposeStore(store);

app.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider, useDispatch, useSelector } from 'react-redux';
import { wrapStore } from 'redux-in-worker';

const initialState = { count: 0 };
const worker = new Worker(new URL('./store.worker', import.meta.url));
const store = wrapStore(worker, initialState);

const Counter = () => {
  const dispatch = useDispatch();
  const count = useSelector(state => state.count);
  return (
    <div>
      count: {count}
      <button type="button" onClick={() => dispatch({ type: 'increment' })}>+1</button>
      <button type="button" onClick={() => dispatch({ type: 'decrement' })}>-1</button>
    </div>
  );
};

const App = () => (
  <Provider store={store}>
    <Counter />
    <Counter />
  </Provider>
);

ReactDOM.render(<App />, document.getElementById('app'));

Examples

The examples folder contains working examples. You can run one of them with

PORT=8080 npm run examples:01_minimal

and open http://localhost:8080 in your web browser.

Blogs