英文:
React createProtal called outsite a JSX component not updating the DOM
问题
I am trying to render a dynamically generated react component in a react app using createPortal.
When I call createPortal from a class the component is not rendered.
Handler.ts
the class that contains the business logic
export class Handler {
private element: HTMLElement | null;
constructor(selector: string) {
this.element = document.getElementById(selector);
}
attachedEvent() {
this.element?.addEventListener("mouseenter", () => {
let cancel = setTimeout(() => {
if (this.element != null)
this.attachUi(this.element)
}, 1000)
this.element?.addEventListener('mouseleave', () => {
clearTimeout(cancel)
})
})
}
attachUi(domNode: HTMLElement) {
createPortal(createElement(
'h1',
{className: 'greeting'},
'Hello'
), domNode);
}
}
Main.tsx
the react component that uses Handler.ts
const handler = new Handler("test_comp");
export default function Main() {
useEffect(() => {
// @ts-ignore
handler.useAddEventListeners();
});
return (
<>
<div id="test_comp">
<p>Detect Mouse</p>
</div>
</>
)
}
However, when I replace the attachUi
function with the function below, it works:
attachUi(domNode: HTMLElement) {
const root = createRoot(domNode);
root.render(createElement(
'h1',
{className: 'greeting'},
'Hello'
));
}
}
What am I missing?
<details>
<summary>英文:</summary>
I am trying to render a dynamically generated react component in a react app using createProtal.
When I call createProtal from a class the component is not rendered.
`Handler.ts` the class the contains the business logic
export class Handler {
private element: HTMLElement | null;
constructor(selector: string) {
this.element = document.getElementById(selector);
}
attachedEvent() {
this.element?.addEventListener("mouseenter", () => {
let cancel = setTimeout(() => {
if (this.element != null)
this.attachUi(this.element)
}, 1000)
this.element?.addEventListener('mouseleave', () => {
clearTimeout(cancel)
})
})
}
attachUi(domNode: HTMLElement) {
createPortal(createElement(
'h1',
{className: 'greeting'},
'Hello'
), domNode);
}
}
`Main.tsx` the react component that uses `Handler.ts`
const handler = new Handler("test_comp");
export default function Main() {
useEffect(() => {
// @ts-ignore
handler.useAddEventListeners();
});
return (
<>
<div id="test_comp">
<p>Detect Mouse</p>
</div>
</>
)
}
However when I repleace `attachUi` function with the function below it works
attachUi(domNode: HTMLElement) {
const root = createRoot(domNode);
root.render(createElement(
'h1',
{className: 'greeting'},
'Hello'
));
}
What am I missing?
</details>
# 答案1
**得分**: 1
React使用一种叫做Virtual DOM的东西。只有包含在VDOM中的组件才会显示在屏幕上。组件返回React能理解并包含在VDOM中的内容。
`createPortal(...)` 返回的内容与 `<SomeComponent ... />` 完全相同。
所以,如果你只是这样做:`const something = <SomeComponent />`,而且你没有在任何地方使用这个变量,那么它就不会被显示。`createPortal` 也是一样的。`const something = createPortal(...)`。如果你想显示它,只需在某处使用这个变量。将它添加到VDOM中,让一些你的组件返回它。
你的结构是:
App
-子组件
-孙子组件
-子组件2
而你的Portal在别的地方,它没有附加到那个VDOM上。如果你想要显示它,你必须在那里包含它。
在你下一个示例中使用`root.render`,你创建了一个新的VDOM。它与你的主VDOM分开。这就是为什么它会被显示出来。
<details>
<summary>英文:</summary>
React uses something called Virtual DOM. Only components that are included in that VDOM are displayed to the screen. A component returns something that React understands and includes to the VDOM.
`createPortal(...)` returns exactly the same as `<SomeComponent ... />`
So if you just do: `const something = <SomeComponent />` and you don't use that variable anywhere, you can not display it. The same is with `createPortal`. `const something = createPortal(...)`. Just use that variable somewhere if you want to display it. Add it to VDOM, let some of your components return it.
Your structure is
App
-children
-grand children
-children2
And your portal is somewhere else, that is not attached to that VDOM. You have to include it there, if you want to be displayed.
In your next example using root.render you create new VDOM. It is separated from your main one. This is why it is displayed
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论