Skip to content

Commit 83a8d29

Browse files
committed
fix(docs): stabilize useRefreshKey deps with memoized string conversion
1 parent 5c59606 commit 83a8d29

File tree

3 files changed

+54
-12
lines changed

3 files changed

+54
-12
lines changed

docs/src/content/docs/guides/faq.mdx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,30 @@ If there is a State dependency that can trigger React.useEffect, you can also im
4848

4949
```ts
5050
// e.g. src/hooks/use-refresh-key.ts
51-
import React from 'react'
51+
import { useEffect, useMemo, useState } from 'react'
5252

5353
export const useRefreshKey = (deps: unknown[]) => {
54-
const [refreshKey, setRefreshKey] = React.useState(Date.now())
55-
56-
React.useEffect(() => {
54+
const [refreshKey, setRefreshKey] = useState(Date.now())
55+
56+
/**
57+
* Ensure dependencies are stable between renders. If deps is an array,
58+
* convert it to a string to prevent infinite loops.
59+
*
60+
* ⚠️ Note: `Array.prototype.toString()` is a shallow and order-sensitive
61+
* representation. It may not behave as expected for objects or nested arrays.
62+
* For more accurate results, consider using JSON.stringify() or a deep
63+
* comparison function like lodash.isEqual().
64+
*/
65+
const effectDeps = useMemo(
66+
() => (Array.isArray(deps) ? deps.toString() : deps),
67+
[deps],
68+
)
69+
70+
useEffect(() => {
5771
requestAnimationFrame(() => {
5872
setRefreshKey(Date.now())
5973
})
60-
}, [deps])
74+
}, [effectDeps])
6175

6276
return {
6377
refreshKey,

docs/src/content/docs/zh/guides/faq.mdx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,30 @@ const onResize = () => setRefreshKey(Date.now())
4848

4949
```ts
5050
// e.g. src/hooks/use-refresh-key.ts
51-
import React from 'react'
51+
import { useEffect, useMemo, useState } from 'react'
5252

5353
export const useRefreshKey = (deps: unknown[]) => {
54-
const [refreshKey, setRefreshKey] = React.useState(Date.now())
55-
56-
React.useEffect(() => {
54+
const [refreshKey, setRefreshKey] = useState(Date.now())
55+
56+
/**
57+
* 确保依赖项在渲染之间保持稳定。如果 deps 是数组,
58+
* 将其转换为字符串以防止进入无限循环。
59+
*
60+
* ⚠️ 注意:`Array.prototype.toString()` 是浅层的且对顺序敏感,
61+
* 对于对象或嵌套数组,可能不会按预期工作。
62+
* 若需要更准确的判断,可考虑使用 JSON.stringify(),
63+
* 或像 lodash.isEqual() 这样的深度比较函数。
64+
*/
65+
const effectDeps = useMemo(
66+
() => (Array.isArray(deps) ? deps.toString() : deps),
67+
[deps],
68+
)
69+
70+
useEffect(() => {
5771
requestAnimationFrame(() => {
5872
setRefreshKey(Date.now())
5973
})
60-
}, [deps])
74+
}, [effectDeps])
6175

6276
return {
6377
refreshKey,

docs/src/hooks/use-refresh-key.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1-
import { useEffect, useState } from 'react'
1+
import { useEffect, useMemo, useState } from 'react'
22

33
export const useRefreshKey = (deps: unknown[]) => {
44
const [refreshKey, setRefreshKey] = useState(Date.now())
55

6+
/**
7+
* Ensure dependencies are stable between renders. If deps is an array,
8+
* convert it to a string to prevent infinite loops.
9+
*
10+
* ⚠️ Note: `Array.prototype.toString()` is a shallow and order-sensitive
11+
* representation. It may not behave as expected for objects or nested arrays.
12+
* For more accurate results, consider using JSON.stringify() or a deep
13+
* comparison function like lodash.isEqual().
14+
*/
15+
const effectDeps = useMemo(
16+
() => (Array.isArray(deps) ? deps.toString() : deps),
17+
[deps],
18+
)
19+
620
useEffect(() => {
721
requestAnimationFrame(() => {
822
setRefreshKey(Date.now())
923
})
10-
}, [deps])
24+
}, [effectDeps])
1125

1226
return {
1327
refreshKey,

0 commit comments

Comments
 (0)