diff --git a/src/Portal.tsx b/src/Portal.tsx
index 372046b..8699590 100644
--- a/src/Portal.tsx
+++ b/src/Portal.tsx
@@ -1,15 +1,18 @@
import * as React from 'react';
import { createPortal } from 'react-dom';
+import canUseDom from 'rc-util/lib/Dom/canUseDom';
import OrderContext from './Context';
import useDom from './useDom';
import useScrollLocker from './useScrollLocker';
+import { inlineMock } from './mock';
-// ZombieJ: Since React 18 strict mode logic change.
-// We should rewrite for compatible.
+export type ContainerType = Element | DocumentFragment;
+
+export type GetContainer = string | ContainerType | (() => ContainerType);
export interface PortalProps {
/** Customize container element. Default will create a div in document.body when `open` */
- getContainer?: () => Element | DocumentFragment;
+ getContainer?: GetContainer;
children?: React.ReactNode;
/** Show the portal children */
open?: boolean;
@@ -17,6 +20,20 @@ export interface PortalProps {
autoLock?: boolean;
}
+const getPortalContainer = (getContainer: GetContainer) => {
+ if (!canUseDom()) {
+ return null;
+ }
+
+ if (typeof getContainer === 'string') {
+ return document.querySelector(getContainer);
+ }
+ if (typeof getContainer === 'function') {
+ return getContainer();
+ }
+ return getContainer;
+};
+
export default function Portal(props: PortalProps) {
const { open, autoLock, getContainer, children } = props;
@@ -30,7 +47,7 @@ export default function Portal(props: PortalProps) {
}, [open]);
// ======================== Container ========================
- const customizeContainer = getContainer?.();
+ const customizeContainer = getPortalContainer(getContainer);
const [defaultContainer, queueCreate] = useDom(
mergedRender && !customizeContainer,
@@ -39,13 +56,14 @@ export default function Portal(props: PortalProps) {
// ========================= Render ==========================
// Do not render when nothing need render
- if (!mergedRender) {
+ if (!mergedRender || !canUseDom()) {
return null;
}
+ console.log(inlineMock());
return (
- {createPortal(children, mergedContainer)}
+ {inlineMock() ? children : createPortal(children, mergedContainer)}
);
}
diff --git a/src/index.tsx b/src/index.tsx
index 3cb0f84..34fa676 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,6 +1,8 @@
import Portal from './Portal';
import type { PortalProps } from './Portal';
+import { inlineMock } from './mock';
export type { PortalProps };
+export { inlineMock };
export default Portal;
diff --git a/src/mock.ts b/src/mock.ts
new file mode 100644
index 0000000..6fefe84
--- /dev/null
+++ b/src/mock.ts
@@ -0,0 +1,8 @@
+export let inline = false;
+
+export function inlineMock(nextInline?: boolean) {
+ if (typeof nextInline === 'boolean') {
+ inline = nextInline;
+ }
+ return inline;
+}
diff --git a/tests/__snapshots__/testEnv.test.tsx.snap b/tests/__snapshots__/testEnv.test.tsx.snap
new file mode 100644
index 0000000..91bdcb4
--- /dev/null
+++ b/tests/__snapshots__/testEnv.test.tsx.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Test Env inlineMock 1`] = `
+
+ Start
+
+ Hello World
+
+ End
+
+`;
diff --git a/tests/setupAfterEnv.ts b/tests/setupAfterEnv.ts
new file mode 100644
index 0000000..7b0828b
--- /dev/null
+++ b/tests/setupAfterEnv.ts
@@ -0,0 +1 @@
+import '@testing-library/jest-dom';
diff --git a/tests/ssr.test.tsx b/tests/ssr.test.tsx
new file mode 100644
index 0000000..20f3d6c
--- /dev/null
+++ b/tests/ssr.test.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import Portal from '../src';
+
+jest.mock('rc-util/lib/Dom/canUseDom', () => () => false);
+
+describe('SSR', () => {
+ it('No Render in SSR', () => {
+ const { unmount } = render(
+
+ Hello World
+ ,
+ );
+
+ expect(document.querySelector('.bamboo')).toBeFalsy();
+
+ unmount();
+ });
+});
diff --git a/tests/testEnv.test.tsx b/tests/testEnv.test.tsx
new file mode 100644
index 0000000..4cf04e6
--- /dev/null
+++ b/tests/testEnv.test.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import Portal, { inlineMock } from '../src';
+
+describe('Test Env', () => {
+ it('inlineMock', () => {
+ inlineMock(true);
+
+ const { container } = render(
+ <>
+ Start
+
+ Hello World
+
+ End
+ >,
+ );
+
+ expect(container).toMatchSnapshot();
+ });
+});