SolidJSS
SolidJSโ€ข4y agoโ€ข
3 replies
FutureLights

Better way of reusing event listeners for hooks

I have a hook for the window size.

import { Accessor, onCleanup, onMount } from 'solid-js';
import { createSignal } from 'solid-js';

export const useWindowSize = (): {
    width: Accessor<number>;
    height: Accessor<number>;
} => {
    const [width, setWidth] = createSignal(0);
    const [height, setHeight] = createSignal(0);

    const handle = () => {
        setWidth(window.innerWidth);
        setHeight(window.innerHeight);
    };

    onMount(() => {
        window.addEventListener('resize', handle);
        handle();
    });

    onCleanup(() => window.removeEventListener('resize', handle))

    return { width, height };
}


It works great, but I want to reuse my event listener because I'll be using this hook in many components. I can always do something like below, but there has to be a better way to do it with something that SolidJS provids? Or even JS.

import { Accessor, onCleanup, onMount } from 'solid-js';
import { createSignal } from 'solid-js';

type Callback = (width: number, height: number) => void;

const cbMap: {[key: string]: Callback} = {};

const handleEvent = () => {
    let w = window.innerWidth;
    let h = window.innerHeight;
    Object.values(cbMap).forEach(cb => cb(w, h));
}

window.addEventListener('resize', handleEvent);

const sub = (uuid: string, cb: Callback) => {
    cbMap[uuid] = cb;
    return uuid;
}

const unsub = (uuid: string) => {
    delete cbMap[uuid];
}

export const useWindowSize = (): {
    width: Accessor<number>;
    height: Accessor<number>;
} => {
    const [width, setWidth] = createSignal(window.innerWidth);
    const [height, setHeight] = createSignal(window.innerHeight);
    var uuid = crypto.randomUUID();

    const handle = (w: number, h: number) => {
        setWidth(w);
        setHeight(h);
    };

    onMount(() => {
        sub(uuid, handle);
    });

    onCleanup(() => unsub(uuid))

    return { width, height };
}
Was this page helpful?