elf-sync-state-yomo
Version:
Syncs elf store state across tabs
94 lines (64 loc) • 3.96 kB
Markdown
[](https://www.npmjs.com/package/elf-sync-state) [](https://github.com/RicardoJBarrios/elf-sync-state/blob/main/LICENSE.md) [](https://github.com/RicardoJBarrios/elf-sync-state)
> Syncs elf store state across tabs
The `syncState()` function gives you the ability to synchronize an [elf store](https://ngneat.github.io/elf/) state across multiple tabs, windows or iframes using the [Broadcast Channel API](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API).
First, you need to install the package via npm:
```bash
npm i elf-sync-state
```
To use it you should call the `syncState()` function passing the store:
```ts
import { createStore, withProps } from '@ngneat/elf';
import { syncState } from 'elf-sync-state';
interface AuthProps {
user: { id: string } | null;
token: string | null;
}
const authStore = createStore(
{ name: 'auth' },
withProps<AuthProps>({ user: null, token: null })
);
syncState(authStore);
```
As the second parameter you can pass an optional `Options` object, which can be used to define the following:
- `channel`: the name of the channel (by default - the store name plus a `@store` suffix).
- `source`: a function that receives the store and return what to sync from it. The default is `(store) => store`.
- `preUpdate`: a function to map the event message and get the data. The default is `(event) => event.data`.
- `runGuard`: a function that returns whether the actual implementation should be run. The default is `() => typeof window !== 'undefined' && typeof window.BroadcastChannel !== 'undefined'`.
```ts
import { syncState } from 'elf-sync-state';
import { authStore } from './auth.store';
syncState(authStore, { channel: 'auth-channel' });
```
The sync state also returns the [`BroadcastChannel`](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) object created or `undefined` if the `runGuard` function returns `false`.
```ts
import { syncState } from 'elf-sync-state';
import { authStore } from './auth.store';
const channel: BroadcastChannel | undefined = syncState(authStore);
```
The `includeKeys()` operator can be used to sync a subset of the state:
```ts
import { includeKeys, syncState } from 'elf-sync-state';
import { authStore } from './auth.store';
syncState(authStore, {
source: (store) => store.pipe(includeKeys(['user'])),
});
```
The `preUpdate` option can be used to intercept the [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)
and modify the data to be synchronized taking into account other properties of the event.
```ts
import { includeKeys, syncState } from 'elf-sync-state';
import { authStore } from './auth.store';
syncState(authStore, {
preUpdate: (event) => {
console.log(event);
return event.origin === '' ? undefined : event.data;
},
});
```
The use of this library has been tested together with other Elf libraries, such as [elf-entities](https://ngneat.github.io/elf/docs/features/entities/entities), [elf-persist-state](https://ngneat.github.io/elf/docs/features/persist-state) or [elf-state-history](https://ngneat.github.io/elf/docs/features/history). I have also tried to be consistent with their programming style and documentation to help with integration.
[](https://stackblitz.com/edit/angular-elf-sync-state?devToolsHeight=33&file=src/app/todo.repository.ts) you can see an example of using all of these in an Angular application. Just open the result in two different tabs to see the library in action.
> :warning: There may be a desync due to hot reload