You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:03:06