【问题标题】:How to create an element with ref and then append it as a child element如何使用 ref 创建元素,然后将其附加为子元素
【发布时间】:2021-07-22 12:19:33
【问题描述】:

我想将一个div元素附加到Parent,Parent是一个高度封装的组件,我只能得到它的ref,现在我创建一个元素使用React.createElement(),因为我可以同时为元素创建ref,然后我尝试使用appendChild() 将此元素附加到父级,但失败了。

const demo: React.FC = () => {
    const parentRef = useRef<HTMLElement>(null);

    // append child
    const childRef = useRef<HTMLElement>(null)
    let child = React.createElement("div",{ref:childRef})

    useEffect(() =>{
        if(parentRef.current) {
            parentRef.current.appendChild(child)  // error
        }
    },[])

    return (
        <>
            <Parent
              ref={parentRef}
              {...allprops}
            />
        </>
    )
};
export default demo;

我收到一个错误:'DetailedReactHTMLElement' 类型的参数不可分配给'Node' 类型的参数。

如果我使用let child = document.createElement("div") 创建子元素,则不会出现此错误,但我无法为子元素创建 ref(或者我不知道如何)。

我能做些什么来解决它?提前谢谢你!

【问题讨论】:

  • 在任何情况下都不应在反应中使用appendChild

标签: reactjs typescript


【解决方案1】:

如果我理解正确,您正试图将 React 组件插入到另一个您只有 DOM 引用的组件中。

您提供的代码的问题是React.createElement() 创建了一个在 React 的虚拟 DOM 中使用的 React 元素,而HTMLElement.appendChild() 需要一个普通的 DOM 节点。

您或许可以通过门户实现此目的:

  1. 使用parentRef 插入一个DOM 节点('child')。
  2. 将 DOM 节点的引用存储在 childRef 中。
  3. 使用childRef 作为门户的容器。

注意:以下代码未经测试,但如果您想进一步研究,应该为您指明大致的方向。

const InsertedContent: React.FC = ({ container, children }) => {
    if (!container) {
        return null;
    }

    return ReactDOM.createPortal(
        children, 
        container
    );
}

const demo: React.FC = () => {
    const parentRef = useRef<HTMLElement>(null);

    const childRef = useRef<HTMLElement>(null)

    useEffect(() =>{
        if(parentRef.current) {
            const child = document.createElement('div');
            childRef.current = child;
            parentRef.current.appendChild(child);
        }
    },[])

    return (
        <>
            <Parent
              ref={parentRef}
              {...allprops}
            />
            <InsertedContent container={childRef.current}>
                This is some content to stick into the child.
            </InsertedContent>
        </>
    )
};

export default demo;

【讨论】:

  • 谢谢!但是我已经放弃了修改那个组件,创建一个新的比在原始组件上强行添加一个新节点要好得多。无论如何,谢谢你的建议,我相信它对未来会有帮助。
猜你喜欢
  • 2020-01-21
  • 2022-06-19
  • 2014-12-26
  • 1970-01-01
  • 2011-11-07
  • 1970-01-01
  • 1970-01-01
  • 2012-11-04
  • 1970-01-01
相关资源
最近更新 更多