electron-shared-state
Version:
❤️ easily sharing state across electron main and renderer processes.
142 lines (100 loc) • 3.94 kB
Markdown
# electron-shared-state






Sharing state between main and renderer process can be this easy.
- 🚀 Mutate your state while keep them in sync with other process
- 🎯 Write in typescript with full typing support
- ❤️ Elegant and easy to learn API
- 👻 Immutability and structural sharing out of the box with built-in immer

## Install
```sh
npm install electron-shared-state
```
or
```sh
yarn add electron-shared-state
```
## Usage
You can check source code under [example directory](/example).
```ts
// shared
export const initialState = 0;
// renderer
import { createSharedStore } from 'electron-shared-state';
const sharedStore = createSharedStore(initialState);
sharedStore.subscribe((state) => {
console.log(state);
});
setTimeout(() => {
sharedStore.setState((state) => {
state = state + 1;
});
}, 2000);
// main
import { createSharedStore } from 'electron-shared-state';
const sharedStore = createSharedStore(initialState);
sharedStore.subscribe((state) => {
console.log(state);
});
// both main and renderer will print the state after two seconds.
```
If your project already using state management tools like redux, you can easily replace a slice of your state with electron-shared-state, so you can just share part of the state you want to share without create a whole state tree in both processes.
```ts
// renderer
const sharedStore = createSharedStore(initialState);
// split state into a reducer
function sharedReducer(state, action) {
switch (action.type) {
case 'some action type':
const nextState = sharedStore.setState(...);
return nextState;
}
}
// combine with other reducer
const rootReducer = combindReducers({
other: ...,
shared: sharedReducer,
...
});
// create redux store
const store = createStore(rootReducer)
// in main process
// only this part of state will be shared across main and renderer
export const store = createSharedStore(initialState);
```
## API Reference
electron-shared-state only provides one simple function: `createSharedStore`. The signature is like below:
```ts
interface Options {
name?: string;
}
function createSharedStore<T>(
state: T,
options?: Options
): {
setState: (recipe: (draft: T) => void, description?: string | undefined) => T;
getState: () => T;
subscribe: (
listener: (state: T, description?: string | undefined) => void
) => () => void;
};
```
The input is the state your want to share across processes, generally it's an object.
It also accepts an optional `Option` object, you can pass a store name if you want to have multiple stores.
```ts
const s1 = createSharedStore(..., { name: 's1' })
const s2 = createSharedStore(..., { name: 's2' })
```
It returns a Store object with a few methods on it.
**`setState(stateUpdater, description)`**
Accepts a stateUpdater function and a description string for debug purpose. The stateUpdater is like the second argument of immer's produce, so it inherits [immer's pitfalls](https://immerjs.github.io/immer/docs/pitfalls).
Returns the new state. It use immer underneath so the state remains immutable, to keep it in sync across processes, you should always use setState to update it.
**`getState()`**
Returns the current state.
**`subscribe(listener)`**
Adds a change listener. It will be called any time the state is changed, the listener receives the latest state and a description string as arguments.