Skip to content

Commit

Permalink
➕ Add skip feature to workaround joshwcomeau#92
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielAtCosmicDNA committed Apr 5, 2024
1 parent 2265105 commit 9694c80
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 32 deletions.
1 change: 1 addition & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default function useSound(
soundEnabled,
interrupt,
onload,
skip,
...delegated
}?: HookOptions
): ReturnedValue;
45 changes: 19 additions & 26 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import useOnMount from './use-on-mount';
import useMount from 'use-mount';

import { HookOptions, PlayOptions, PlayFunction, ReturnedValue } from './types';

Expand All @@ -13,11 +13,11 @@ export default function useSound<T = any>(
soundEnabled = true,
interrupt = false,
onload,
skip = false,
...delegated
}: HookOptions<T> = {} as HookOptions
) {
const HowlConstructor = React.useRef<HowlStatic | null>(null);
const isMounted = React.useRef(false);

const [duration, setDuration] = React.useState<number | null>(null);

Expand All @@ -29,7 +29,7 @@ export default function useSound<T = any>(
onload.call(this);
}

if (isMounted.current) {
if (isMounted) {
// @ts-ignore
setDuration(this.duration() * 1000);
}
Expand All @@ -39,29 +39,22 @@ export default function useSound<T = any>(
};

// We want to lazy-load Howler, since sounds can't play on load anyway.
useOnMount(() => {
import('howler').then(mod => {
if (!isMounted.current) {
// Depending on the module system used, `mod` might hold
// the export directly, or it might be under `default`.
HowlConstructor.current = mod.Howl ?? mod.default.Howl;

isMounted.current = true;

new HowlConstructor.current({
src: Array.isArray(src) ? src : [src],
volume,
rate: playbackRate,
onload: handleLoad,
...delegated,
});
}
});

return () => {
isMounted.current = false;
};
});
const { isMounted } = useMount(async () => {
if (!skip) {
const mod = await import('howler');
// Depending on the module system used, `mod` might hold
// the export directly, or it might be under `default`.
HowlConstructor.current = mod.Howl ?? mod.default.Howl;

new HowlConstructor.current({
src: Array.isArray(src) ? src : [src],
volume,
rate: playbackRate,
onload: handleLoad,
...delegated,
});
}
}, [skip]);

// When the `src` changes, we have to do a whole thing where we recreate
// the Howl instance. This is because Howler doesn't expose a way to
Expand Down
1 change: 1 addition & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface HookOptions {
interrupt?: boolean;
soundEnabled?: boolean;
sprite?: SpriteMap;
skip?: boolean;
onload?: () => void;
}
export interface PlayOptions {
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type HookOptions<T = any> = T & {
interrupt?: boolean;
soundEnabled?: boolean;
sprite?: SpriteMap;
skip?: boolean;
onload?: () => void;
};

Expand Down
8 changes: 8 additions & 0 deletions src/use-mount.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DependencyList } from 'react';
declare const useMount: (
callback?: Function,
deps?: DependencyList
) => {
isMounted: boolean;
};
export default useMount;
24 changes: 24 additions & 0 deletions src/use-mount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { DependencyList, useRef } from 'react';
import useOnMount from './use-on-mount';

const useMount = (callback: Function = () => {}, deps: DependencyList = []) => {
// Ref to track component mount state
const isMounted = useRef(false);

useOnMount(() => {
// Component has mounted, set the flag
if (!isMounted.current) {
isMounted.current = true;
callback();
}

// Cleanup function to reset the flag when component unmounts
return () => {
isMounted.current = false;
};
}, deps);

return { isMounted: isMounted.current };
};

export default useMount;
8 changes: 6 additions & 2 deletions src/use-on-mount.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
import * as React from 'react';
export default function useOnMount(callback: React.EffectCallback): void;
import { EffectCallback, DependencyList } from 'react';
declare const useOnMount: (
callback: EffectCallback,
deps?: DependencyList
) => void;
export default useOnMount;
10 changes: 6 additions & 4 deletions src/use-on-mount.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as React from 'react';
import { useEffect, EffectCallback, DependencyList } from 'react';

export default function useOnMount(callback: React.EffectCallback) {
React.useEffect(callback, []);
}
const useOnMount = (callback: EffectCallback, deps: DependencyList = []) => {
useEffect(callback, deps);
};

export default useOnMount;

0 comments on commit 9694c80

Please sign in to comment.