我在 React 应用程序中使用 Next JS,但在门户中创建模态时遇到问题,它抛出错误“目标容器不是 DOM 元素”。,这是我的代码。
import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classes from './listModal.scss';
const EditorListModal = (props) => {
let container;
if (typeof window !== 'undefined') {
const rootContainer = document.createElement('div');
const parentElem = document.querySelector('#__next');
parentElem.appendChild(rootContainer);
container = rootContainer;
}
const isShown = props.show ? classes['editor-listModal--open'] : '';
const element = (
<div className={`${classes['editor-listModal']} ${isShown}`}>
// Modal Content
</div>
);
return ReactDOM.createPortal(element, container);
};
EditorListModal.propTypes …Run Code Online (Sandbox Code Playgroud) 我想在 NextJS 13.4 中创建一个 Modal(使用新的layout.tsx 文件系统),但我做不到。由于这是一个新事物,我在网上也找不到解决方案。
以下是我尝试过的事情:
编辑:
import React from "react";
import { createPortal } from "react-dom";
const Modal = () => {
return createPortal(
<React.Fragment>
<div>your content</div>
</React.Fragment>,
Document.body as HTMLElement
);
};
export default Modal;
Run Code Online (Sandbox Code Playgroud)
它会抛出:
文档未定义
尝试从“next/document”导入文档,但仍然无法正常工作。
另一个错误是error Error: createPortal was called on the server. Portals are not currently supported on the server. Update your program to conditionally call createPortal on the client only.
我在第一行添加了“使用客户端”,它将解决该错误。
但仍然没有显示模态内容的结果。
由于本教程的第 1 步是创建一个 …
因此,门户解决的一个有趣且令人惊奇的属性是保留来自提供者的上下文,即使您的组件需要在其他地方呈现也是如此。如果您使用 ContextProvider 包装组件子树,则在该子树中呈现的任何组件都将有权访问上下文值。
反过来,如果您在子树之外渲染某些内容,它就无法访问该上下文。React Portals 解决了这个问题,所以如果你想渲染子树之外的东西,你可以在同一个子树内完成它。我认为React 文档对此有所涉及:
无论子级是否是门户,诸如上下文之类的功能都完全相同,因为无论 DOM 树中的位置如何,门户仍然存在于 React 树中。
我想我并没有概念化它实际上是如何工作的。React Portal 如何能够访问 Context 而无需在同一子树中渲染?听起来在幕后,Portal 是“React Tree”的一部分?那么一定有一些奇特的“传递信息然后渲染门户逻辑”?明确我的问题
门户究竟如何工作来保留对上下文值的访问?
基本场景是这样的:我有一个width: 100%在样式表中定义的组件。因此它应该保留其父组件的宽度。我想计算我的组件的宽度并将其应用于我的子组件,因为我通过渲染它createPortal并且我希望它们具有相同的宽度。这在浏览器中有效。但是,在我的测试中,我发现它window.getComputedStyle(component)没有返回任何从样式表应用的样式。
正如建议的那样,我可以模拟 javascript 窗口,但这实际上与我希望做的事情背道而驰,我认为。我想验证浏览器中存在的行为,该行为window.getComputedStyle()返回应用的所有样式,而不仅仅是内联样式。
我把一个简单的例子放到了一个代码盒中:https ://codesandbox.io/s/goofy-wilson-6v4dp
也在这里:
function App() {
return (
<div className="App">
<WidthComponent />
</div>
)
}
function WidthComponent() {
const myInput = useRef();
const [inputWidth, setInputWidth] = useState(0);
useEffect(() => {
console.log("in handleLoad");
const width = myInput.current ? myInput.current.offsetWidth : 0;
setInputWidth(width);
}, [myInput]);
return (
<div className="inherited-width" ref={myInput}>
<div style={{ width: inputWidth }} className="child-element">
Hello
</div>
</div>
);
}
// test
test("width is inherited", () => …Run Code Online (Sandbox Code Playgroud)reactjs jestjs react-testing-library react-portal use-effect
我在我的reactjs应用程序中使用react-portal。我创建了两个根元素,一个用于渲染 React 应用程序,另一个用于 React-portal:
<html>
<head></head>
<body>
<div id='react-root-element' />
<div id='react-portal-root-element' />
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
我还有一个组件 MyComponent,它使用react-portal 将内容渲染到react-portal-root-element。内容由具有 id 的 div 元素(我们称其为“container-div”)包装。
我的组件:
export class MyComponent extends React.Component {
// constructor ...
render() {
return (
<Portal node={ 'react-portal-root-element' }>
<div id='divTest_id'>
// some more content
</div>
</Portal>
);
}
}
Run Code Online (Sandbox Code Playgroud)
MyComponent 的父级:
export class MyComponentParent extends React.Component {
// ...
someMethod => {
this.setState({ myProp: someNewValue });
}
render() {
return (
<div>
<MyComponent someProp={ this.state.myProp } />
</div> …Run Code Online (Sandbox Code Playgroud) 我想让它像https://tailwindui.com/components/application-ui/overlays/modals上的第一个模式一样居中
\n我在下面的模态上复制了相同的类,但无法将其垂直居中。课程是完全相同的。
\n这是 React Portal 的问题吗?
\nimport * as React from "react"\nimport { Dialog } from "@headlessui/react"\n\ntype ModalProps = {\n isOpen: boolean\n setIsOpen: React.Dispatch<React.SetStateAction<boolean>>\n}\n\nexport const Modal = ({ isOpen, setIsOpen }: ModalProps) => {\n return (\n <Dialog\n open={isOpen}\n onClose={setIsOpen}\n as="div"\n className="fixed inset-0 z-10 overflow-y-auto"\n >\n <div className="flex flex-col bg-gray-800 text-white w-96 mx-auto py-8 px-4 text-center">\n <Dialog.Overlay />\n\n <Dialog.Title className="text-red-500 text-3xl">\n Deactivate account\n </Dialog.Title>\n <Dialog.Description className="text-xl m-2">\n This will permanently deactivate your account\n </Dialog.Description>\n\n <p …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 slate-react 制作一个编辑器。我制作了一个悬停菜单,但 Next.js 渲染存在样式问题。所以我尝试createPortal在 Next.js 的默认 id 下使用 React __next。但我越来越Error: Target container is not a DOM element.错误。
下面是我的代码:
import React, { useRef, useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { ReactEditor, useSlate } from "slate-react";
import { Button } from "@material-ui/core";
import { Menu, Portal } from "./component";
import FormatBoldIcon from "@material-ui/icons/FormatBold";
import FormatItalicIcon from "@material-ui/icons/FormatItalic";
import FormatUnderlinedIcon from "@material-ui/icons/FormatUnderlined";
import TextFieldsIcon from "@material-ui/icons/TextFields";
import FormatSizeIcon from "@material-ui/icons/FormatSize";
import FormatQuoteIcon from …Run Code Online (Sandbox Code Playgroud) 我使用 popper.js 实现了 Popper 组件,并使用 React 的 Portal 来渲染 popper 元素。
现在我想预览我的 popper 组件,但它无法在 Storybook.js 上创建门户
这是我的方法。
.storybook/preview.js
import { ThemeProvider } from 'emotion-theming';
import { Global } from '@emotion/react';
import { theme, normalize } from 'custom-theme';
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
export const decorators = [
Story => (
<>
<ThemeProvider theme={theme}>
<Global styles={normalize} />
{Story()}
<div id="popper-root"></div>
</ThemeProvider>
</>
),
];
Run Code Online (Sandbox Code Playgroud)
门户网站.tsx …
react-portal ×8
reactjs ×8
next.js ×3
javascript ×2
html ×1
jestjs ×1
modal-dialog ×1
portal ×1
storybook ×1
tailwind-css ×1
use-effect ×1