Skip to content

Commit 1a5649c

Browse files
committed
docs: add faq
1 parent 08ad795 commit 1a5649c

File tree

6 files changed

+273
-2
lines changed

6 files changed

+273
-2
lines changed

docs/astro.config.mts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ export default defineConfig({
104104
},
105105
link: '/guides/getting-started',
106106
},
107+
{
108+
label: 'Frequently Asked Questions',
109+
translations: {
110+
zh: '常见问题',
111+
},
112+
link: '/guides/faq',
113+
},
107114
{
108115
label: 'About',
109116
translations: {

docs/src/components/AppliesTo.tsx

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import React, { Fragment, useMemo } from 'react'
2+
import pkg from '../../../package.json'
3+
import { getTranslation, type Languages } from '@/i18n'
4+
5+
const repoUrl = pkg.repository.url
6+
7+
const supports = ['Truncate', 'ShowMore', 'MiddleTruncate'] as const
8+
9+
interface AppliesToProps {
10+
lang: Languages
11+
components: (typeof supports)[number][]
12+
}
13+
14+
export const AppliesTo: React.FC<AppliesToProps> = ({
15+
lang,
16+
components = supports,
17+
}) => {
18+
const title = getTranslation(lang, 'appliesTo.title')
19+
20+
const componentsDisplay = supports.map((name) => {
21+
const checked = components.includes(name)
22+
if (!checked) return null
23+
return <span key={name}>{name}</span>
24+
})
25+
26+
return (
27+
<blockquote className="flex items-center gap-2 w-full mt-6">
28+
{title}
29+
<span className="flex items-center gap-3">{componentsDisplay}</span>
30+
</blockquote>
31+
)
32+
}
33+
34+
const formatGitHubIssue = (url: string) => {
35+
const pattern = /github\.com\/([^\/]+\/[^\/]+)\/issues\/(\d+)/
36+
const match = url.match(pattern)
37+
38+
if (match) {
39+
const [, repo, issueId] = match
40+
return `${repo}#${issueId}`
41+
}
42+
43+
return null
44+
}
45+
46+
interface IssueConfig {
47+
issueId: string
48+
href: string
49+
}
50+
51+
const isIssueConfig = (v: unknown): v is IssueConfig => Boolean(v)
52+
53+
export const RelatedIssues: React.FC<{
54+
lang: Languages
55+
issues: (string | number)[]
56+
}> = ({ lang, issues }) => {
57+
const title = getTranslation(lang, 'appliesTo.relatedIssues')
58+
59+
const issuesDisplay = useMemo(() => {
60+
return issues
61+
.map((issue) => {
62+
const isIssueHref =
63+
typeof issue === 'string' && issue.startsWith('https://')
64+
const isIssueId = typeof issue === 'number'
65+
66+
if (!isIssueHref && !isIssueId) return null
67+
68+
const href = isIssueHref ? issue : `${repoUrl}/issues/${issue}`
69+
const issueId = isIssueId ? `#${issue}` : formatGitHubIssue(issue)
70+
71+
if (!issueId) return null
72+
73+
return {
74+
issueId,
75+
href,
76+
} satisfies IssueConfig
77+
})
78+
.filter(isIssueConfig)
79+
.map(({ issueId, href }, index) => {
80+
return (
81+
<Fragment key={href}>
82+
<a href={href} target="_blank" rel="noopener noreferrer">
83+
{issueId}
84+
</a>
85+
{index < issues.length - 1 && ', '}
86+
</Fragment>
87+
)
88+
})
89+
}, [issues])
90+
91+
return (
92+
<blockquote className="flex items-center gap-2 w-full">
93+
{title}
94+
<span className="flex items-center gap-2">{issuesDisplay}</span>
95+
</blockquote>
96+
)
97+
}

docs/src/components/StatisticalData.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useMemo } from 'react'
2+
import clsx from 'clsx'
23
import pkg from '../../../package.json'
34
import type { Languages } from '@/i18n'
4-
import clsx from 'clsx'
55

66
const name = pkg.name
77
const repoUrl = pkg.repository.url
@@ -17,9 +17,14 @@ const options = [
1717
},
1818
{
1919
link: `https://www.npmjs.com/package/${name}`,
20-
image: `https://img.shields.io/npm/dt/${name}?color=${color}&label=downloads`,
20+
image: `https://img.shields.io/npm/dy/${name}?color=${color}&label=downloads`,
2121
title: 'Download counts',
2222
},
23+
{
24+
link: `https://codecov.io/gh/${repo}`,
25+
image: `https://codecov.io/gh/${repo}/graph/badge.svg?token=K9W9KRBTMA&color=${color}`,
26+
title: 'Test Coverage',
27+
},
2328
{
2429
link: repoUrl,
2530
image: `https://img.shields.io/github/stars/${repo}?style=social`,
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
title: Frequently Asked Questions
3+
description: Answers to problems that may be easily encountered by developers, as well as some interesting problems reported in GitHub issues.
4+
---
5+
6+
import { AppliesTo, RelatedIssues } from '@/components/AppliesTo'
7+
8+
## Why is the component not updated when only the container width changes?
9+
10+
<AppliesTo client:only="react" lang="en" />
11+
<RelatedIssues client:only="react" lang="en" issues={[18]} />
12+
13+
Currently, the component has a built-in listener for the [Window: resize event](https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event) . When this event is triggered, the component recalculates its width and updates the displayed content.
14+
15+
However, in some cases, such as when using [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels) , only the container element’s width changes while the browser window width remains the same. In these scenarios, the component will not automatically adjust its size.
16+
17+
### Reasons for not processing
18+
19+
To avoid unnecessary performance overhead, the component does not include a built-in [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) for parent elements. Therefore, when the container size changes without a window resize event, developers need to decide when to trigger a re-render to ensure the component responds correctly to layout adjustments.
20+
21+
### Recommended solution
22+
23+
Recommend to use a `key` to trigger re-truncate, nodes will re-render when a `key` is updated, this is [React's ability](https://react.dev/reference/react/useState#resetting-state-with-a-key) .
24+
25+
#### Trigger via callback API
26+
27+
Set a variable and bind `key={refreshKey}` to the element that needs to respond to resize changes.
28+
29+
```tsx
30+
const [refreshKey, setRefreshKey] = useState(Date.now())
31+
32+
// e.g. `<Truncate key={refreshKey} />`
33+
```
34+
35+
When the element triggers a resize change, update this value.
36+
37+
```tsx
38+
const onResize = () => setRefreshKey(Date.now())
39+
40+
// e.g. `<Panel onResize={onResize} />`
41+
```
42+
43+
> Online demo: [CodeSandbox](https://codesandbox.io/p/sandbox/react-resizable-panels-forked-tjt38f?file=%2Fsrc%2FApp.js)
44+
45+
#### Trigger via dependency
46+
47+
If there is a State dependency that can trigger React.useEffect, you can also implement it this way, declaring a common Hook.
48+
49+
```ts
50+
// e.g. src/hooks/use-refresh-key.ts
51+
import React from 'react'
52+
53+
export const useRefreshKey = (deps: unknown[]) => {
54+
const [refreshKey, setRefreshKey] = React.useState(Date.now())
55+
56+
React.useEffect(() => {
57+
requestAnimationFrame(() => {
58+
setRefreshKey(Date.now())
59+
})
60+
}, [deps])
61+
62+
return {
63+
refreshKey,
64+
}
65+
}
66+
```
67+
68+
Treat the related state as a dependency. When the dependency changes, the value of `refreshKey` will be automatically updated.
69+
70+
```tsx
71+
const [width, setWidth] = useState(DEFAULT_WIDTH_VALUE)
72+
const [lines, setLines] = useState(DEFAULT_LINES_VALUE)
73+
74+
const { refreshKey } = useRefreshKey([width, lines])
75+
76+
// e.g. `<Truncate key={refreshKey} />`
77+
```
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
title: 常见问题
3+
description: 可能容易被开发者遇到的问题解答,以及一些在 GitHub issue 反馈过的有意思的问题。
4+
---
5+
6+
import { AppliesTo, RelatedIssues } from '@/components/AppliesTo'
7+
8+
## 为什么仅容器宽度变化时没有更新组件?
9+
10+
<AppliesTo client:only="react" lang="zh" />
11+
<RelatedIssues client:only="react" lang="zh" issues={[18]} />
12+
13+
目前,组件内置了对 [Window:Resize 事件](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/resize_event) 的监听,当该事件触发时,会重新计算组件宽度,并更新显示内容。
14+
15+
然而,在某些场景下,例如使用 [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels) ,仅容器元素宽度变化,而浏览器窗口宽度保持不变,此时组件不会自动调整尺寸。
16+
17+
### 不处理的原因
18+
19+
为了避免不必要的性能开销,组件未内置对父节点的 [ResizeObserver](https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver) 监听。因此,当容器尺寸变化但窗口尺寸未变时,需要开发者自行决定触发重新渲染的时机,以确保组件正常响应布局调整。
20+
21+
### 推荐的解决方案
22+
23+
建议使用 `key` 来触发重新截断,当 `key` 更新时,节点将重新渲染,这是 [React 的能力](https://zh-hans.react.dev/reference/react/useState#resetting-state-with-a-key)
24+
25+
#### 通过回调 API 触发
26+
27+
设置一个变量,绑定 `key={refreshKey}` 到需要响应 Resize 变化的元素上。
28+
29+
```tsx
30+
const [refreshKey, setRefreshKey] = useState(Date.now())
31+
32+
// e.g. `<Truncate key={refreshKey} />`
33+
```
34+
35+
当元素触发调整大小变化时,更新此值。
36+
37+
```tsx
38+
const onResize = () => setRefreshKey(Date.now())
39+
40+
// e.g. `<Panel onResize={onResize} />`
41+
```
42+
43+
> 在线 demo: [CodeSandbox](https://codesandbox.io/p/sandbox/react-resizable-panels-forked-tjt38f?file=%2Fsrc%2FApp.js)
44+
45+
#### 通过依赖触发
46+
47+
如果存在能够触发 React.useEffect 的 State 依赖,也可以这样实现,声明一个通用的 Hook 。
48+
49+
```ts
50+
// e.g. src/hooks/use-refresh-key.ts
51+
import React from 'react'
52+
53+
export const useRefreshKey = (deps: unknown[]) => {
54+
const [refreshKey, setRefreshKey] = React.useState(Date.now())
55+
56+
React.useEffect(() => {
57+
requestAnimationFrame(() => {
58+
setRefreshKey(Date.now())
59+
})
60+
}, [deps])
61+
62+
return {
63+
refreshKey,
64+
}
65+
}
66+
```
67+
68+
将相关的 state 作为依赖,当依赖变化时,会自动更新 `refreshKey` 的值。
69+
70+
```tsx
71+
const [width, setWidth] = useState(DEFAULT_WIDTH_VALUE)
72+
const [lines, setLines] = useState(DEFAULT_LINES_VALUE)
73+
74+
const { refreshKey } = useRefreshKey([width, lines])
75+
76+
// e.g. `<Truncate key={refreshKey} />`
77+
```

docs/src/i18n/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export const translations = {
2525
'collapser.collapse': 'Collapse',
2626
'collapser.expand': 'Expand',
2727
'collapser.name': 'Code',
28+
29+
// AppliesTo
30+
'appliesTo.title': 'Applies to:',
31+
'appliesTo.relatedIssues': 'Related issues:',
2832
},
2933
zh: {
3034
separator: '',
@@ -41,6 +45,10 @@ export const translations = {
4145
'collapser.collapse': '收起',
4246
'collapser.expand': '展开',
4347
'collapser.name': '代码',
48+
49+
// AppliesTo
50+
'appliesTo.title': '适用于:',
51+
'appliesTo.relatedIssues': '相关 issue :',
4452
},
4553
} as const
4654

0 commit comments

Comments
 (0)