ResizeObserver触发组件尺寸变化时,方法调用传入旧props值的问题求助
ResizeObserver触发组件尺寸变化时,方法调用传入旧props值的问题求助
我遇到了一个组件相关的问题,想请大家帮忙看看。
我期望当props.zoomValue变化时,onUpdateScale方法能被调用,并且拿到最新的zoomValue,但实际情况是,方法里拿到的不是最新值,而是组件首次渲染时的值。举个例子:组件初始创建时zoomValue是1.0,之后这个值变成1.5,但onUpdateScale里最终拿到的还是1.0——我通过控制台调试发现,函数先是用新值调用了一次,但紧接着又用旧值调用了第二次,这怎么可能发生啊?
我已经确认ResizeObserver的创建和销毁是正确的,就算是在断开连接时触发调用,也说不通——因为下一个Observer创建时又会调用一次函数,但结果还是不对。
这个bug是我偶然发现的,现在完全找不到修复思路。在我看来更新函数的写法是没问题的,到底哪里漏掉了?
说明一下,这个代码片段用的是Preact和Bootstrap框架。
import { useLayoutEffect, useRef, useState } from "preact/hooks"; import type { JSX } from "preact/jsx-runtime"; export interface WidgetFormContainerProps { vWidth: string | number, zoomValue: number, children?: any, } export const WidgetFormContainer = (props: WidgetFormContainerProps): JSX.Element => { const [width, setWidth] = useState<number>(0); const [height, setHeight] = useState<number>(0); const [scale, setScale] = useState<number>(1.0); const root = useRef<HTMLDivElement>(null); const container = useRef<HTMLDivElement>(null); const onUpdateScale = (): void => { if (!root.current || !container.current) { // won't update with no elements. return; } const newScale = (root.current.clientWidth / container.current.clientWidth) * props.zoomValue; const newWidth = Math.max(container.current.clientWidth * newScale, root.current.clientWidth); const newHeight = container.current.clientHeight * newScale; setScale(newScale); setWidth(newWidth); setHeight(newHeight); } useLayoutEffect(() => { if (!root.current) { // required root element to create observer, destroy previous observer if any. return; } const observer = new ResizeObserver(onUpdateScale); observer.observe(root.current); onUpdateScale(); return () => observer.disconnect(); }, [root.current]); useLayoutEffect(onUpdateScale, [props.zoomValue]); return ( <div class="w-100 h-100 overflow-y-scroll overflow-x-auto" ref={root} > <div class="position-relative" style={{ width: `${width.toFixed(0)}px`, height: `${height.toFixed(0)}px` }} > <div class="position-absolute top-0 end-50" ref={container} style={{ width: props.vWidth, padding: '48px', transformOrigin: 'top center', transform: `translateX(50%) scale(${scale.toFixed(3)})` }} children={props.children} /> </div> </div>); }
备注:内容来源于stack exchange,提问作者magg
相关产品推荐
相关产品推荐

