常见问题
为什么仅容器宽度变化时没有更新组件?
目前,组件内置了对 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.tsimport { 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} />`