React:在第二个容器中插入(呈现)时如何等到 ref 可用
React: How to wait until ref is available when inserted (rendered) within a second container
编辑:更好的解释
上下文:
我从第三台服务器收到了一些普通的 HTML 代码,我想
- 插入我的 React 应用程序
- 修改它
原生 JS 方法
- 我可以使用正则表达式修改字符串并添加任何带有
id
的 HTML 标签
- 然后我可以像往常一样通过
getElementById
修改这些元素
React 方法
- 我不应该使用 DOM
- 然后我应该在字符串中插入一些内部有 React ref 的组件
- 相反(插入一些 React 组件作为普通 HTML)将通过
ReactDOMServer.renderToString
- 所以,当我用
ReactDOM.render()
注入组件时,问题是 render
方法需要时间,所以如果在下一行我尝试使用存在于插入的组件还不存在
问题
- 怎么做?通常我会将代码放在具有
[]
依赖项的 useEffect
中,但在这里我是 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>
);
}
useEffect
与空依赖数组执行 在 第一次渲染后,因此你将在回调中获得 DOM ref:
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
*/
我需要使用 callback ref but encapsulating it within useCallback
to make sure it only rerenders with the dependencies indicated (i.e. none []
), so that it is only executed when the component changes (as explained here)
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>
);
}
编辑:更好的解释
上下文:
我从第三台服务器收到了一些普通的 HTML 代码,我想
- 插入我的 React 应用程序
- 修改它
原生 JS 方法
- 我可以使用正则表达式修改字符串并添加任何带有
id
的 HTML 标签
- 然后我可以像往常一样通过
getElementById
修改这些元素
React 方法
- 我不应该使用 DOM
- 然后我应该在字符串中插入一些内部有 React ref 的组件
- 相反(插入一些 React 组件作为普通 HTML)将通过
ReactDOMServer.renderToString
- 所以,当我用
ReactDOM.render()
注入组件时,问题是render
方法需要时间,所以如果在下一行我尝试使用存在于插入的组件还不存在
问题
- 怎么做?通常我会将代码放在具有
[]
依赖项的useEffect
中,但在这里我是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>
);
}
useEffect
与空依赖数组执行 在 第一次渲染后,因此你将在回调中获得 DOM ref:
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
*/
我需要使用 callback ref but encapsulating it within useCallback
to make sure it only rerenders with the dependencies indicated (i.e. none []
), so that it is only executed when the component changes (as explained here)
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>
);
}