# redux-workerized

> WIP: Not production ready. This is conceptual implementation

Latest version **0.0.10** (published 2018-11-12) · MIT license · 0 weekly downloads

## Install

```sh
npm install redux-workerized
pnpm add redux-workerized
yarn add redux-workerized
bun add redux-workerized
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.0.10 |
| Published | 2018-11-12 |
| First published | 2018-11-11 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 21 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | mizchi |

## Links

- npm: https://www.npmjs.com/package/redux-workerized
- npm.io page: https://npm.io/package/redux-workerized

## Dependencies (1)

- [lodash.isequal](https://npm.io/package/lodash.isequal.md) ^4.5.0

## Recent versions

- 0.0.10 (latest) — 2018-11-12
- 0.0.9 — 2018-11-12
- 0.0.8 — 2018-11-12
- 0.0.7 — 2018-11-11
- 0.0.6 — 2018-11-11
- 0.0.5 — 2018-11-11
- 0.0.4 — 2018-11-11
- 0.0.3 — 2018-11-11
- 0.0.2 — 2018-11-11
- 0.0.1 — 2018-11-11

## README

# redux-workerized

WIP: Not production ready. This is conceptual implementation

- Run reducer and middlewares in worker.
- Type safe API for typescript
- (React) Connect state by react hooks

## How to use

Working example https://github.com/mizchi/redux-workerized-example

Add dependencies.

```
yarn add redux comlinkjs
```

Use https://github.com/parcel-bundler/parcel or https://github.com/webpack-contrib/worker-loader

Put react-hooks.d.ts to your typescript env https://gist.github.com/mizchi/bfc0986c5fd3c695a38d0d573909efc5

## Example

See full code [examples/react](examples/react)

### WorkerThread

```typescript
// worker.ts
import "@babel/polyfill";
import * as Comlink from "comlinkjs";
import { createStore } from "redux";
import reducer from "./reducer";
import { createWorkerizedStore } from "redux-workerized/worker";

const store = createStore(reducer);
const proxy = createWorkerizedStore(store, s => s);

// Merge with your complink api
Comlink.expose({ ...proxy }, self);
```

## MainThread

```tsx
import "@babel/polyfill";
import { WorkerizedStore } from "../..";
import * as Comlink from "comlinkjs";

// This is counter example. Use your reducer.
import { RootState, increment } from "./reducer";

type CounterSnapshot = {
  value: number;
};

// Use webpack's worker-loader or parcel to build worker instance and cast
const store: WorkerizedStore<RootState, CounterSnapshot> = Comlink.proxy(
  new Worker("./worker.ts")
) as any;

(async () => {
  const subscritionId = await store.subscribe(
    Comlink.proxyValue((snapshot: CounterSnapshot) => {
      console.log("changed", snapshot);
    }),
    Comlink.proxyValue(
      (state: RootState): CounterSnapshot => {
        return state.counter;
      }
    )
  );

  await store.dispatch(increment());
  const currentState = await store.getState();
  console.log("current state", currentState);
  document.body.textContent = JSON.stringify(currentState);
  await store.unsubscribe(subscritionId);
})();
```

`NOTE`: `store.subscribe(...)` needs `Complink.proxyValue(...)` to serialize data from worker

## MainThread with react

Dependencies

```
yarn add react@16.7.0-alpha.0 react-dom@16.7.0-alpha.0
yarn add -d @types/react @types/react-dom
```

```tsx
import "@babel/polyfill";
import React, { useCallback } from "react";
import ReactDOM from "react-dom";
import { createWorkerContext } from "../../react";
import { RootState } from "./reducer";

// build worker

const worker = new Worker("./worker.ts");

const { WorkerContext, useSnapshot, useDispatch, ready } = createWorkerContext(
  worker,
  (state: RootState) => state.counter
);

// components

import { increment, Increment } from "./reducer";
function CounterApp() {
  const value = useSnapshot(state => state.value);
  const dispatch = useDispatch<Increment>();

  const onClick = useCallback(() => {
    dispatch(increment());
  }, []);

  return <button onClick={onClick}>{value}</button>;
}

export function App() {
  return (
    <WorkerContext>
      <CounterApp />
    </WorkerContext>
  );
}

ready.then(() => {
  ReactDOM.render(<App />, document.querySelector(".root"));
});
```

## API

```ts
import { Dispatch, AnyAction } from "redux";

// redux-workerized
export type WorkerizedStore<State, A extends AnyAction = AnyAction> = {
  getState(): Promise<State>;
  dispatch(action: A): Promise<void>;
  subscribe(listener: (state: State) => void): Promise<number>;
  unsubscribe(listenerId: number): Promise<void>;
};

// redux-workerized/react
export declare function createWorkerContext<State>(
  worker: Worker
): {
  WorkerContext: (
    props: {
      children: any;
      fallback?: any;
    }
  ) => any;
  useSnapshot: <Selected>(fn: (state: State) => Selected) => Selected;
  useDispatch: <A extends AnyAction>() => Dispatch<A>;
  ready: Promise<void>;
};
```

## MainThread with Vue

```tsx
import "@babel/polyfill";
import Vue from "vue";
import Vuex from "vuex";
import App from "./App.vue";
import { workerPlugin, proxy } from "redux-workerize/vue";
import { RootState, INCREMENT } from "./reducer";

Vue.use(Vuex);

export type CounterSnapshot = {
  value: number;
};

export type State = {
  remote: CounterSnapshot;
};

const store = new Vuex.Store<State>({
  state: {
    remote: {
      value: 0
    }
  },
  mutations: {
    $sync(state, payload: CounterSnapshot) {
      state.remote = { ...state.remote, ...payload };
    },
    ...proxy([INCREMENT])
  },
  plugins: [
    workerPlugin(
      new Worker("./worker.ts"),
      (state: RootState): CounterSnapshot => {
        return state.counter;
      }
    )
  ]
});

new Vue({
  store,
  el: ".root",
  render(h) {
    return h(App);
  }
});
```

## Run examples

```
yarn install
yarn parcel examples/react/index.html
# open localhost:1234
```

## TODO

- [x] Basic examples
- [x] with percel
- [x] Publish
- [ ] Suppress update by sharrow equal
- [ ] Init with React.Suspense
- [ ] SSR
- [ ] Run in ServiceWorker
- [ ] rollup to umd
- [ ] with webpack example
- [ ] Monorepo

## LICENSE

MIT

---
_Source: https://npm.io/package/redux-workerized · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
