From cde0449c77051e43cd084be792c18de48e4c1a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Tue, 14 Mar 2023 17:01:37 +0800 Subject: [PATCH] fix: SSR should not break (#409) * test: driven * test: test driven * fix: ssr should not break * chore: clean up --- package.json | 10 +++++----- src/Drawer.tsx | 19 ++++++++++++------ tests/ssr.spec.tsx | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 11 deletions(-) create mode 100755 tests/ssr.spec.tsx diff --git a/package.json b/package.json index c0e77bf..4cdcfcf 100644 --- a/package.json +++ b/package.json @@ -54,12 +54,12 @@ "devDependencies": { "@ant-design/icons": "^4.7.0", "@testing-library/jest-dom": "^5.11.9", - "@testing-library/react": "^12.1.5", + "@testing-library/react": "^13.0.0", "@types/classnames": "^2.2.9", "@types/jest": "^27.0.2", "@types/raf": "^3.4.0", - "@types/react": "^17.0.9", - "@types/react-dom": "^17.0.6", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "@types/warning": "^3.0.0", "@umijs/fabric": "^2.0.0", "@umijs/test": "^3.5.23", @@ -72,8 +72,8 @@ "less": "^3.10.3", "np": "^7.5.0", "prettier": "^2.6.2", - "react": "^16.10.2", - "react-dom": "^16.10.2", + "react": "^18.0.0", + "react-dom": "^18.0.0", "typescript": "^4.6.4" } } diff --git a/src/Drawer.tsx b/src/Drawer.tsx index 8c528b0..9cff779 100644 --- a/src/Drawer.tsx +++ b/src/Drawer.tsx @@ -40,15 +40,22 @@ const Drawer: React.FC = props => { warnCheck(props); } + // ============================= Open ============================= + const [internalOpen, setInternalOpen] = React.useState(false); + + useLayoutEffect(() => { + setInternalOpen(open); + }, [open]); + // ============================ Focus ============================= const panelRef = React.useRef(); const lastActiveRef = React.useRef(); useLayoutEffect(() => { - if (open) { + if (internalOpen) { lastActiveRef.current = document.activeElement as HTMLElement; } - }, [open]); + }, [internalOpen]); // ============================= Open ============================= const internalAfterOpenChange: DrawerProps['afterOpenChange'] = @@ -66,13 +73,13 @@ const Drawer: React.FC = props => { }; // ============================ Render ============================ - if (!forceRender && !animatedVisible && !open && destroyOnClose) { + if (!forceRender && !animatedVisible && !internalOpen && destroyOnClose) { return null; } const drawerPopupProps = { ...props, - open, + open: internalOpen, prefixCls, placement, autoFocus, @@ -87,10 +94,10 @@ const Drawer: React.FC = props => { return ( diff --git a/tests/ssr.spec.tsx b/tests/ssr.spec.tsx new file mode 100755 index 0000000..4b6039d --- /dev/null +++ b/tests/ssr.spec.tsx @@ -0,0 +1,50 @@ +import { render } from '@testing-library/react'; +import { renderToString } from 'react-dom/server'; +import React from 'react'; +import Drawer from '../src'; +// import canUseDom from 'rc-util/lib/Dom/canUseDom' + +global.canUseDom = true; + +jest.mock('rc-util/lib/Dom/canUseDom', () => { + // const canUseDom = jest.requireActual('rc-util/lib/Dom/canUseDom'); + return () => global.canUseDom; +}); + +describe('SSR', () => { + beforeEach(() => { + global.canUseDom = true; + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('hydrate should not crash', () => { + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + + const Demo = () => ( + +
+ + ); + + global.canUseDom = false; + const html = renderToString(); + + expect(html).toBeFalsy(); + + global.canUseDom = true; + + const container = document.createElement('div'); + container.innerHTML = html; + document.body.appendChild(container); + + render(, { container, hydrate: true }); + + expect(errSpy).not.toHaveBeenCalled(); + + errSpy.mockRestore(); + }); +});