跳转到内容

常见问题

为什么仅容器宽度变化时没有更新组件?

目前,组件内置了对 Window:Resize 事件 的监听,当该事件触发时,会重新计算组件宽度,并更新显示内容。

然而,在某些场景下,例如使用 react-resizable-panels ,仅容器元素宽度变化,而浏览器窗口宽度保持不变,此时组件不会自动调整尺寸。

不处理的原因

为了避免不必要的性能开销,组件未内置对父节点的 ResizeObserver 监听。因此,当容器尺寸变化但窗口尺寸未变时,需要开发者自行决定触发重新渲染的时机,以确保组件正常响应布局调整。

推荐的解决方案

建议使用 key 来触发重新截断,当 key 更新时,节点将重新渲染,这是 React 的能力

通过回调 API 触发

设置一个变量,绑定 key={refreshKey} 到需要响应 Resize 变化的元素上。

const [refreshKey, setRefreshKey] = useState(Date.now())
// e.g. `<Truncate key={refreshKey} />`

当元素触发调整大小变化时,更新此值。

const onResize = () => setRefreshKey(Date.now())
// e.g. `<Panel onResize={onResize} />`

在线 demo: CodeSandbox

通过依赖触发

如果存在能够触发 React.useEffect 的 State 依赖,也可以这样实现,声明一个通用的 Hook 。

// e.g. src/hooks/use-refresh-key.ts
import { useEffect, useMemo, useState } from 'react'
export const useRefreshKey = (deps: unknown[]) => {
const [refreshKey, setRefreshKey] = useState(Date.now())
/**
* 确保依赖项在渲染之间保持稳定。如果 deps 是数组,
* 将其转换为字符串以防止进入无限循环。
*
* ⚠️ 注意:`Array.prototype.toString()` 是浅层的且对顺序敏感,
* 对于对象或嵌套数组,可能不会按预期工作。
* 若需要更准确的判断,可考虑使用 JSON.stringify(),
* 或像 lodash.isEqual() 这样的深度比较函数。
*/
const effectDeps = useMemo(
() => (Array.isArray(deps) ? deps.toString() : deps),
[deps],
)
useEffect(() => {
requestAnimationFrame(() => {
setRefreshKey(Date.now())
})
}, [effectDeps])
return {
refreshKey,
}
}

将相关的 state 作为依赖,当依赖变化时,会自动更新 refreshKey 的值。

const [width, setWidth] = useState(DEFAULT_WIDTH_VALUE)
const [lines, setLines] = useState(DEFAULT_LINES_VALUE)
const { refreshKey } = useRefreshKey([width, lines])
// e.g. `<Truncate key={refreshKey} />`