【问题标题】:Component fails to correctly render on first passes (React Hooks)组件在第一次传递时无法正确渲染(React Hooks)
【发布时间】:2021-02-16 11:05:01
【问题描述】:

我正在尝试更新渲染从父组件 (A) 传递的 SVG 对象的 React 组件 (B)。

B 然后使用getSVGDocument().?getElementById("groupID") 并添加基于 SVG 组成员的事件处理。

A 还传入一个道具,指示鼠标悬停在单独的菜单中。

B 中的简化代码:

export function ComponentB(props: {
    overviewSvg: string
    highlightKey?: string
}) {
    function getElems(): HTMLElement[] {
        let innerElems = new Array<HTMLElement>()
        const svgObj: HTMLObjectElement = document.getElementById(
            "my_svg"
        ) as HTMLObjectElement
        if (svgObj) {
            const elemGroup = svgObj.getSVGDocument()?.getElementById("elemGroup")
            if (elemGroup) {
                for (let i = 0; i < elemGroup.children.length; i++) {
                    innerElems.push(elemGroup.children[i] as HTMLElement)
                }
            } 
        } 
        return innerElems
    }
    const elems = getElems() // Also tried variations with useState and useEffect, can't seem to get the right combination...
    useEffect(() => {
        console.log("effect called")
        console.log(elems)
        elems?.forEach((elem) => {
            elem.onmousedown = () => toggleColor(elem)
        })
    }, [elems, props.overviewSvg])

    useEffect(() => {
        elems?.forEach((elem) => {
            if (elem.id === props.highlightKey) {
                setActive(elem)
            } else {
                setInactive(elem)
            }
        })
    }, [elems, props.highlightKey, props.overviewSvg])

    return (
        <>
            <object data={props.overviewSvg} id="my_svg" />
        </>
    )
}

我不确定 useEffect 中依赖项的适当参数应该是什么,或者这是否完全是错误的方法?

控制台显示,在加载时,elems 的数组通常为空,在这种情况下onmousedown 循环当然不会添加任何函数。

父级设置props.highlightKey后,触发第二个函数,然后触发第一个效果并添加mousedown函数。

在任何父 highlightKey 更改之前,我应该进行哪些更改才能使组件正确呈现?

【问题讨论】:

    标签: reactjs react-hooks state


    【解决方案1】:

    通过使用 useRef 并将其应用于 DOM 元素,然后向该元素添加 onload 行为,我能够获得所需的行为。

    // Get a ref for the <object> element
    const svgObj = useRef<HTMLObjectElement>(null)
    const [elemArr, setElems] = useState(Array<HTMLElement>())    
    
    if (svgObj.current) {
        svgObj.current.onload = () => {
            const elems = getElems()
            elems.forEach((elem) => {
                elem.onmousedown = () => toggleColor(elem)
            })
            setElems(elems)
        }
    }
    
    useEffect(() => {
        elemArr.forEach((elem) => {
            if (elem.id === props.highlightKey) {
                setActive(elem)
            } else {
                setInactive(elem)
            }
        })
    }, [elemArr, props.highlightKey])
    
    return (
        <object ref={svgObj} data={props.overviewSVG} ... />
    )
    

    【讨论】:

      猜你喜欢
      • 2021-09-09
      • 1970-01-01
      • 2021-02-16
      • 2021-05-31
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多