当一个 ReactNode
类型的节点,没有在 render
函数内时,如何渲染到页面上呢?
就需要借助 react-dom/client
中的 createRoot
函数,同时在不需要的时候销毁所有内容。
所以,就搞一个 hook
函数,函数加载的时候节点被 render
到页面上,函数卸载的时候卸载所有内容。同时增加当节点内容变化时更新 DOM 的功能。
tsx
import React, { FC, useRef, useState, useEffect, type ReactNode } from 'react'
import { createRoot, type Root } from 'react-dom/client'
type useRenderDocumentProps = (renderNode: ReactNode) => void
const useRenderDocument: useRenderDocumentProps = (renderNode) => {
const rootRef = useRef<HTMLDivElement | null>(null)
const rootInstanceRef = useRef<Root | null>(null)
const prevNode = useRef(renderNode)
useEffect(() => {
if (rootInstanceRef.current && prevNode.current !== renderNode) {
rootInstanceRef.current.render(renderNode)
prevNode.current = renderNode
}
}, [renderNode])
useEffect(() => {
if (!rootInstanceRef.current) {
const root = document.createElement('div')
root.className = 'render-root'
document.body.appendChild(root)
rootRef.current = root
rootInstanceRef.current = createRoot(root)
rootInstanceRef.current.render(renderNode)
}
return () => {
console.log('销毁')
if (rootRef.current) {
rootRef.current.remove()
rootRef.current = null
rootInstanceRef.current?.unmount()
rootInstanceRef.current = null
}
}
}, [])
}
export default useRenderDocument