Skip to content

Commit cde0449

Browse files
authored
fix: SSR should not break (#409)
* test: driven * test: test driven * fix: ssr should not break * chore: clean up
1 parent 94a9e58 commit cde0449

File tree

3 files changed

+68
-11
lines changed

3 files changed

+68
-11
lines changed

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@
5454
"devDependencies": {
5555
"@ant-design/icons": "^4.7.0",
5656
"@testing-library/jest-dom": "^5.11.9",
57-
"@testing-library/react": "^12.1.5",
57+
"@testing-library/react": "^13.0.0",
5858
"@types/classnames": "^2.2.9",
5959
"@types/jest": "^27.0.2",
6060
"@types/raf": "^3.4.0",
61-
"@types/react": "^17.0.9",
62-
"@types/react-dom": "^17.0.6",
61+
"@types/react": "^18.0.0",
62+
"@types/react-dom": "^18.0.0",
6363
"@types/warning": "^3.0.0",
6464
"@umijs/fabric": "^2.0.0",
6565
"@umijs/test": "^3.5.23",
@@ -72,8 +72,8 @@
7272
"less": "^3.10.3",
7373
"np": "^7.5.0",
7474
"prettier": "^2.6.2",
75-
"react": "^16.10.2",
76-
"react-dom": "^16.10.2",
75+
"react": "^18.0.0",
76+
"react-dom": "^18.0.0",
7777
"typescript": "^4.6.4"
7878
}
7979
}

src/Drawer.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,22 @@ const Drawer: React.FC<DrawerProps> = props => {
4040
warnCheck(props);
4141
}
4242

43+
// ============================= Open =============================
44+
const [internalOpen, setInternalOpen] = React.useState(false);
45+
46+
useLayoutEffect(() => {
47+
setInternalOpen(open);
48+
}, [open]);
49+
4350
// ============================ Focus =============================
4451
const panelRef = React.useRef<HTMLDivElement>();
4552

4653
const lastActiveRef = React.useRef<HTMLElement>();
4754
useLayoutEffect(() => {
48-
if (open) {
55+
if (internalOpen) {
4956
lastActiveRef.current = document.activeElement as HTMLElement;
5057
}
51-
}, [open]);
58+
}, [internalOpen]);
5259

5360
// ============================= Open =============================
5461
const internalAfterOpenChange: DrawerProps['afterOpenChange'] =
@@ -66,13 +73,13 @@ const Drawer: React.FC<DrawerProps> = props => {
6673
};
6774

6875
// ============================ Render ============================
69-
if (!forceRender && !animatedVisible && !open && destroyOnClose) {
76+
if (!forceRender && !animatedVisible && !internalOpen && destroyOnClose) {
7077
return null;
7178
}
7279

7380
const drawerPopupProps = {
7481
...props,
75-
open,
82+
open: internalOpen,
7683
prefixCls,
7784
placement,
7885
autoFocus,
@@ -87,10 +94,10 @@ const Drawer: React.FC<DrawerProps> = props => {
8794

8895
return (
8996
<Portal
90-
open={open || forceRender || animatedVisible}
97+
open={internalOpen || forceRender || animatedVisible}
9198
autoDestroy={false}
9299
getContainer={getContainer}
93-
autoLock={mask && (open || animatedVisible)}
100+
autoLock={mask && (internalOpen || animatedVisible)}
94101
>
95102
<DrawerPopup {...drawerPopupProps} />
96103
</Portal>

tests/ssr.spec.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { render } from '@testing-library/react';
2+
import { renderToString } from 'react-dom/server';
3+
import React from 'react';
4+
import Drawer from '../src';
5+
// import canUseDom from 'rc-util/lib/Dom/canUseDom'
6+
7+
global.canUseDom = true;
8+
9+
jest.mock('rc-util/lib/Dom/canUseDom', () => {
10+
// const canUseDom = jest.requireActual('rc-util/lib/Dom/canUseDom');
11+
return () => global.canUseDom;
12+
});
13+
14+
describe('SSR', () => {
15+
beforeEach(() => {
16+
global.canUseDom = true;
17+
jest.useFakeTimers();
18+
});
19+
20+
afterEach(() => {
21+
jest.useRealTimers();
22+
});
23+
24+
it('hydrate should not crash', () => {
25+
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
26+
27+
const Demo = () => (
28+
<Drawer open>
29+
<div className="bamboo" />
30+
</Drawer>
31+
);
32+
33+
global.canUseDom = false;
34+
const html = renderToString(<Demo />);
35+
36+
expect(html).toBeFalsy();
37+
38+
global.canUseDom = true;
39+
40+
const container = document.createElement('div');
41+
container.innerHTML = html;
42+
document.body.appendChild(container);
43+
44+
render(<Demo />, { container, hydrate: true });
45+
46+
expect(errSpy).not.toHaveBeenCalled();
47+
48+
errSpy.mockRestore();
49+
});
50+
});

0 commit comments

Comments
 (0)