npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

use-post-message-ts

v0.1.7

Published

Use the window.postChannel in React easily with hooks or Zustand, and Typescript!

Readme

use-post-message-ts

Version Build Size GitHub Workflow Status (with branch) GitHub

Note: This project is forked from use-broadcast.

Easily synchronize state across browser tabs and iframes—even across different origins—using window.postMessage in React, Zustand, and TypeScript. If you require synchronization within the same origin only, please consider using use-broadcast-ts instead.

npm install use-post-message-ts

This package allows you to use the window.postMessage across open windows and iframes. It is useful when you want to share state between different tabs or iframes with different origins.

Check out the demo!

Usage with Zustand

// useStore.ts
import { create } from 'zustand';
import { shared } from 'use-post-message-ts';

type MyStore = {
    count: number;
    set: (n: number) => void;
};

const useStore = create<MyStore>(
    shared(
        (set) => ({
            count: 0,
            set: (n) => set({ count: n })
        }),
        { name: 'my-channel', targetOriginUrls: ['http://localhost:3000'], targetElementIFrameIds: [document.getElementById('iframe')] }
    )
);

// MyComponent.tsx
import { FC } from 'react';

const MyComponent: FC = () => {
    const count = useStore((s) => s.count);
    const set = useStore((s) => s.set);

    return (
        <p>
            <p>Count: {count}</p>
            <button onClick={() => set(10)}/>
        </p>
    );
}

export default MyComponent;

You can use the Zustand store like any other Zustand store, but the store will be shared between all windows and iframes.

On the first "render" of the store, the middleware will check if the store already exists in another tab/window. If the store exists, it will be synchronized; otherwise, the store will be created.

If no tab is opened, the store will be created and will be shared as the "main" with the other tabs/windows.

Usage with hooks

import { FC } from 'react';
import { usePostMessage } from 'use-post-message-ts';

const MyComponent: FC = () => {
    const { state, send } = usePostMessage<{ value: number }>('my-channel', { value: 0 });

    return (
        <>
            <p>My value is: {state.value}</p>
            <button onClick={() => send({ value: 10 })} />
        </>
    );
};

export default MyComponent;

With the example above, the component will re-render when the channel receives or sends a value.

import { FC, useEffect } from 'react';
import { usePostMessage } from 'use-post-message-ts';

const MyComponent: FC = () => {
    const { send, subscribe } = usePostMessage<{ value: number }>('my-post-message-channel', { value: 0 }, { subscribe: true });

    useEffect(() => {
	    const unsub = subscribe(({ value }) => console.log(`My new value is: ${value}`));

	    return () => unsub();
    }, []);

    return (
        <>
            <button onClick={() => send({ value: 10 })} />
        </>
    );
};

export default MyComponent;

With the example above, the component will not re-render when the channel receives or sends a value but will call the subscribe callback.

API

shared (Zustand)

shared(
    (set, get, ...) => ...,
    options?: SharedOptions
);

Parameters

options

Type: SharedOptions

The options of the hook.

options.name

Type: string

The name of the channel to use.

options.targetOriginUrls

Type: targetOriginUrls (default: [targetWindow.origin])

The target origins to send the message to. If the target origin is not in the list, the message will be sent to its own origin.

options.targetElementIFrameIds

Type: targetElementIFrameIds[] (default: [])

The target iframes to send the message to. If the target iframe is not in the list, the message will be sent to all iframes so be aware of that.

options.mainTimeout

Type: number (default: 100)

The timeout in ms to wait for the main tab to respond.

options.unsync

Type: boolean (default: false)

If true, the store will only synchronize once with the main tab. After that, the store will be unsynchronized.

options.skipSerialization

Type: boolean (default false)

If true, will not serialize the state with JSON.parse(JSON.stringify(state)) before sending it. This results in a performance boost, but you will have to ensure there are no unsupported types in the state or it will result in errors. See section What data can I send? for more info.

options.partialize

Type: (state: T) => Partial<T> (default: undefined)

Similar to partialize in the Zustand persist middleware, allows you to pick which of the state's fields are sent to other tabs. Can also be used to pre-process the state before it's sent if needed.

options.merge

Type: (state: T, receivedState: Partial<T>) => T (default: undefined)

Similar to merge in the Zustand persist middleware. A custom function that allows you to merge the current state with the state received from another tab.

usePostMessage (hooks)

usePostMessage<T>(name: string, value?: T, options?: UsePostMessageOptions): {
    state: T;
    send: (value: T) => void;
    subscribe: (callback: (e: T) => void) => () => void;
};

Parameters

name

Type: string

The name of the channel to use.

value

Type: T (default: undefined)

The initial value of the channel.

options

Type: UsePostMessageOptions (default: {})

The options of the hook.

options.subscribe

Type: boolean | undefined (default: undefined)

If true, the hook will not re-render the component when the channel receives a new value but will call the subscribe callback.

Return

state

Type: T

The current value of the channel.

send

Type: (value: T) => void

Send a new value to the channel.

subscribe

Type: (callback: (e: T) => void) => () => void

Subscribe to the channel. The callback will be called when the channel receives a new value and when the options.subscribe is set to true.

What data can I send?

You can send any of the supported types by the structured clone algorithm and JSON.stringify, such as:

  • String
  • Boolean
  • Number
  • Array
  • Object
  • Date
  • ...

In short, you cannot send:

  • Function
  • DOM Element
  • BigInt (This is only unsupported by JSON.stringify, so if you set skipSerialization=true, BigInts will work)
  • And some other types

See the MDN documentation for more information. However, if needed, you could use partialize to convert an unsupported type to a string and convert it back on the other end by providing a merge function.

License

MIT