我ReactDOM.createPortal在有状态组件的 render 方法中使用过,如下所示:
class MyComponent extends Component {
...
render() {
return (
<Wrapper>
{ReactDOM.createPortal(<FOO />, 'dom-location')}
</Wrapper>
)
}
}
Run Code Online (Sandbox Code Playgroud)
...但它也可以被无状态(功能)组件使用吗?
Sam*_*uel 27
将加入一个您不想手动更新 index.html 并添加额外标记的选项,此代码段将为您动态创建一个 div,然后插入子项。
export const Portal = ({ children, className = 'root-portal', el = 'div' }) => {
const [container] = React.useState(() => {
// This will be executed only on the initial render
// https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
return document.createElement(el);
});
React.useEffect(() => {
container.classList.add(className)
document.body.appendChild(container)
return () => {
document.body.removeChild(container)
}
}, [])
return ReactDOM.createPortal(children, container)
}
Run Code Online (Sandbox Code Playgroud)
对于固定组件,可以这样做:
const MyComponent = () => ReactDOM.createPortal(<FOO/>, 'dom-location')
Run Code Online (Sandbox Code Playgroud)
或者,为了使函数更灵活,通过传递一个componentprop:
const MyComponent = ({ component }) => ReactDOM.createPortal(component, 'dom-location')
Run Code Online (Sandbox Code Playgroud)
它也可以被无状态(功能)组件使用吗?
是的。
const Modal = (props) => {
const modalRoot = document.getElementById('myEle');
return ReactDOM.createPortal(props.children, modalRoot,);
}
Run Code Online (Sandbox Code Playgroud)
内部渲染:
render() {
const modal = this.state.showModal ? (
<Modal>
<Hello/>
</Modal>
) : null;
return (
<div>
<div id="myEle">
</div>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
TSX 版本基于@Samuel 的回答(React 17,TS 4.1):
// portal.tsx
import * as React from 'react'
import * as ReactDOM from 'react-dom'
interface IProps {
className? : string
el? : string
children : React.ReactNode
}
/**
* React portal based on /sf/answers/4140805511/
* @param children Child elements
* @param className CSS classname
* @param el HTML element to create. default: div
*/
const Portal : React.FC<IProps> = ( { children, className, el = 'div' } : IProps ) => {
const [container] = React.useState(document.createElement(el))
if ( className )
container.classList.add(className)
React.useEffect(() => {
document.body.appendChild(container)
return () => {
document.body.removeChild(container)
}
}, [])
return ReactDOM.createPortal(children, container)
}
export default Portal
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11605 次 |
| 最近记录: |