Skip to content

Commit bf81779

Browse files
committed
docs: add use-singleton
1 parent ab0a86c commit bf81779

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

docs/src/pages/_meta.json

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"use-is-client": {},
4747
"use-isomorphic-layout-effect": {},
4848
"use-retimer": {},
49+
"use-singleton": {},
4950
"use-stable-handler-only-when-you-know-what-you-are-doing-or-you-will-be-fired": {
5051
"title": "useStableHandler"
5152
},

docs/src/pages/use-singleton.mdx

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
title: useSingleton
3+
---
4+
5+
# useSingleton
6+
7+
import ExportMetaInfo from '../components/export-meta-info';
8+
9+
<ExportMetaInfo />
10+
11+
The React documentation's ["Avoiding recreating the ref contents" pattern](https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents) as a hook.
12+
13+
**Before:**
14+
15+
```tsx
16+
function Video() {
17+
const playerRef = useRef(null);
18+
if (playerRef.current === null) {
19+
playerRef.current = new VideoPlayer();
20+
}
21+
// ...
22+
```
23+
24+
**After:**
25+
26+
```tsx
27+
function Video() {
28+
const playerRef = useSingleton(() => new VideoPlayer());
29+
// ...
30+
```
31+
32+
## Usage
33+
34+
```tsx copy
35+
import { useCallback, useEffect } from 'react';
36+
import { useSingleton } from 'foxact/use-singleton';
37+
38+
interface VideoProps {
39+
videoSrc: string;
40+
}
41+
42+
function Video({ videoSrc }: VideoProps) {
43+
const playerRef = useSingleton(() => new VideoPlayer());
44+
45+
// callback ref to attach the player to the video element
46+
const videoElementCallbackRef = useCallback((el: HTMLVideoElement | null) => {
47+
if (el) {
48+
playerRef.current.attach(el);
49+
playerRef.current.load(videoSrc);
50+
} else {
51+
playerRef.current.destroy();
52+
}
53+
}, [videoSrc]);
54+
55+
return <video ref={videoElementCallbackRef} />;
56+
}
57+
```
58+
59+

src/use-singleton/index.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@ export interface SingletonRefObject<T> {
66
readonly current: T
77
}
88

9+
/** @see https://foxact.skk.moe/use-singleton */
910
export const useSingleton = <T>(initializor: () => T): SingletonRefObject<T> => {
1011
const r = useRef<T>();
11-
12-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- it will be undefined only on first render
1312
if (!r.current) {
1413
r.current = initializor();
1514
}
1615

1716
// We are using singleton approach here, to prevent repeated initialization.
1817
// The value will only be written by the hook during the first render and it
19-
// should not be written by anyone else
18+
// should not be written by anyone else anymore
2019
// @ts-expect-error -- see above
2120
return r;
2221
};

0 commit comments

Comments
 (0)