React:在第二个容器中插入(渲染)时如何等待 ref 可用

GWo*_*ing 12 javascript reactjs react-hooks use-effect use-ref

编辑:更好的解释

上下文:

我从第三台服务器收到一些纯 HTML 代码,我想要

  • 插入我的 React 应用程序
  • 修改它

普通的 JS 方法

  • 我可以使用正则表达式修改字符串并添加任何带有id
  • 然后我可以getElementById像往常一样通过 修改这些元素

React 方法

  • 我不应该使用 DOM
  • 然后我应该在字符串中插入一些内部有 React ref 的组件
  • 相反(以纯 HTML 形式插入一些 React 组件)将通过ReactDOMServer.renderToString
  • 因此,当我使用 注入组件时ReactDOM.render(),问题是该render方法需要时间,因此,如果在下一行中我尝试使用插入组件中存在的引用,但该引用尚未存在

问题

  • 怎么做?通常我会将代码放在useEffect带有[]依赖项的 a 中,但这里我是rendering应用程序已安装时的组件
  • 一个快速的解决方法是只进行 500 毫秒的异步等待,然后我可以访问ref,但肯定有更好的东西

此代码失败,因为当ref呈现时它仍然不可用,因此ref.current未定义

我该如何等待呢?

代码沙盒

编辑:我提供了有效的代码,但通过直接 DOM,我认为应该避免这种情况

import React, { useRef, useEffect } from "react";
import ReactDOM from "react-dom";

export default function App() {
  const myref = useRef();

  useEffect(() => {
    const Com = () => <div ref={myref}>hello</div>;
    ReactDOM.render(<Com />, document.getElementById("container"));
    console.log(myref.current); // undefined
    document.getElementById('container').textContent = "direct DOM works"

   // the next line fails since the ref is not yet available
   // myref.current.textContent = "but this REF is not available"; // fails
  }, []);

  const plainhtml = '<div><div id="container"></div><div>some more content</div><div id="another">even more content</div></div>'; // this is some large HTML fetched from an external server

  return (
    <div>
      <h1>Hello CodeSandbox</h1>
      <div dangerouslySetInnerHTML={{ __html: plainhtml }} />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

Den*_*ash 7

useEffect空依赖数组在第一次渲染后执行,因此您将在回调中获得 DOM 引用:

const htmlString = '<div id="container">Hello</div>';

export default function App() {
  const myRef = useRef();

  useEffect(() => {
    if (myRef.current) {
      myRef.current.textContent = 'whats up';
    }
    console.log(myRef.current);
  }, []);

  return (
    <div>
      <div ref={myRef} dangerouslySetInnerHTML={{ __html: htmlString }} />
      <div dangerouslySetInnerHTML={{ __html: htmlString }} />
    </div>
  );
}

/* App renders:
whats up
Hello
*/
Run Code Online (Sandbox Code Playgroud)

编辑神经格莱德-8rtxb


GWo*_*ing 3

我需要使用回调引用,但将其封装在其中useCallback以确保它仅使用指示的依赖项(即 none [])重新呈现,以便仅在组件更改时执行它(如此处所述

代码沙盒

import React, { useEffect, useCallback } from "react";
import ReactDOM from "react-dom";

export default function App() {
  const measuredRef = useCallback(node => {
    if (node !== null) {
      node.textContent = "useCallback DOM also works";
    }
  }, []);

  useEffect(() => {
    const Com = () => <div ref={measuredRef}>hello</div>;
    ReactDOM.render(<Com />, document.getElementById("container"));
    document.getElementById("container").textContent = "direct DOM works";
  }, []);

  const plainhtml = '<div id="container"></div>';

  return (
    <div>
      <h1>Hello CodeSandbox</h1>
      <div dangerouslySetInnerHTML={{ __html: plainhtml }} />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)