From 862729d103ebd78791198191201c6f42a9cd356f Mon Sep 17 00:00:00 2001 From: eps1lon Date: Tue, 9 Nov 2021 19:05:25 +0100 Subject: [PATCH 01/14] Current behavior for useId --- package.json | 2 + packages/react/__tests__/rehydration.js | 72 +++++++++++++++++++++++++ yarn.lock | 25 +++++++++ 3 files changed, 99 insertions(+) diff --git a/package.json b/package.json index 879aefcb2..6c9f77c5d 100644 --- a/package.json +++ b/package.json @@ -261,6 +261,8 @@ "react-router-dom": "^4.2.2", "react-scripts": "1.1.5", "react-test-renderer": "16.8.6", + "react18": "npm:react@alpha", + "react18-dom": "npm:react-dom@alpha", "svg-tag-names": "^1.1.1", "through": "^2.3.8", "unified": "^6.1.6", diff --git a/packages/react/__tests__/rehydration.js b/packages/react/__tests__/rehydration.js index 1245ec161..58530e788 100644 --- a/packages/react/__tests__/rehydration.js +++ b/packages/react/__tests__/rehydration.js @@ -17,6 +17,7 @@ let ReactDOMServer let createCache let css let jsx +let styled let CacheProvider let Global let createEmotionServer @@ -35,6 +36,7 @@ const resetAllModules = () => { CacheProvider = emotionReact.CacheProvider Global = emotionReact.Global createEmotionServer = require('@emotion/server/create-instance').default + styled = require('@emotion/styled').default } const removeGlobalProp = prop => { @@ -592,3 +594,73 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe `) }) + +describe('react18', () => { + let previousIsReactActEnvironment + beforeAll(() => { + jest + .mock('react', () => { + return jest.requireActual('react18') + }) + .mock('react-dom', () => { + return jest.requireActual('react18-dom') + }) + .mock('react-dom/server', () => { + return jest.requireActual('react18-dom/server') + }) + + previousIsReactActEnvironment = global.IS_REACT_ACT_ENVIRONMENT + global.IS_REACT_ACT_ENVIRONMENT = true + }) + + afterAll(() => { + jest.clearAllMocks() + global.IS_REACT_ACT_ENVIRONMENT = previousIsReactActEnvironment + }) + + test('no hydration mismatch when using useId', () => { + const finalHTML = disableBrowserEnvTemporarily(() => { + resetAllModules() + + const StyledDivWithId = styled(function DivWithId({ className }) { + const id = (React: any).useId() + return
+ })({ + border: '1px solid black' + }) + + return ReactDOMServer.renderToString() + }) + + safeQuerySelector('body').innerHTML = `
${finalHTML}
` + + resetAllModules() + + const StyledDivWithId = styled(function DivWithId({ className }) { + const id = (React: any).useId() + return
+ })({ + border: '1px solid black' + }) + + ;(React: any).unstable_act(() => { + ReactDOM.hydrateRoot(safeQuerySelector('#root'), ) + }) + + expect((console.error: any).mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "Warning: Prop \`%s\` did not match. Server: %s Client: %s%s", + "id", + "\\"R:2\\"", + "\\"R:0\\"", + " + at div + at className (/home/eps1lon/Development/forks/emotion/packages/react/__tests__/rehydration.js:639:57) + at Styled(DivWithId) (/home/eps1lon/Development/forks/emotion/packages/react/src/context.js:38:19)", + ], + ] + `) + expect((console.warn: any).mock.calls).toMatchInlineSnapshot(`Array []`) + }) +}) diff --git a/yarn.lock b/yarn.lock index dd247b03e..029d35143 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23995,6 +23995,23 @@ react-timer-mixin@^0.13.4: resolved "https://registry.npmjs.org/react-timer-mixin/-/react-timer-mixin-0.13.4.tgz#75a00c3c94c13abe29b43d63b4c65a88fc8264d3" integrity sha512-4+ow23tp/Tv7hBM5Az5/Be/eKKF7DIvJ09voz5LyHGQaqqz9WV8YMs31eFvcYQs7d451LSg7kDJV70XYN/Ug/Q== +"react18-dom@npm:react-dom@alpha": + version "18.0.0-alpha-327d5c484-20211106" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.0.0-alpha-327d5c484-20211106.tgz#f8855d8e73876b5dbf6545ca02e14d8644a48008" + integrity sha512-yI2Kxy4/+nAFYHtC5uVIwXPURABwBhtqbEgjgRa9cITHsmZIO7AqDee0a5nXVSr8wWmtmbN1vSh29aDicuO03A== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler "0.21.0-alpha-327d5c484-20211106" + +"react18@npm:react@alpha": + version "18.0.0-alpha-327d5c484-20211106" + resolved "https://registry.yarnpkg.com/react/-/react-18.0.0-alpha-327d5c484-20211106.tgz#f0e29b20b8c371697207a9f7b73a7ab625bee4b7" + integrity sha512-CB3JnXquQ9FYkd8IpTlvdpyk+HN1fOUDB7NabXTfbycqqRxuKhtijv7W7F/mbTzPLLMrxV5LwUqrLFc25Zy+UQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + react@16.14.0: version "16.14.0" resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" @@ -25339,6 +25356,14 @@ scheduler@0.19.1, scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" +scheduler@0.21.0-alpha-327d5c484-20211106: + version "0.21.0-alpha-327d5c484-20211106" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0-alpha-327d5c484-20211106.tgz#16340fd4c7387ff58ad897b64715c0e3098e9489" + integrity sha512-VzlBG9d8m/2GwzXMjh7FoV6lpv/vOKdUYFCw3FCVY2aP/lN4oJkKwOlf4on2vEk855ckx+s3bR4eJLrlD7kZSw== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler@^0.13.6: version "0.13.6" resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889" From 2d79250792f3309aa29d7fd6fc8dabde5ee3091a Mon Sep 17 00:00:00 2001 From: eps1lon Date: Tue, 9 Nov 2021 12:29:27 +0100 Subject: [PATCH 02/14] fix(styled): Ensure no hydration mismatch with React.useId --- packages/react/__tests__/rehydration.js | 15 +------------ packages/styled/src/base.js | 28 ++++++++++++++----------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/packages/react/__tests__/rehydration.js b/packages/react/__tests__/rehydration.js index 58530e788..afc799e23 100644 --- a/packages/react/__tests__/rehydration.js +++ b/packages/react/__tests__/rehydration.js @@ -647,20 +647,7 @@ describe('react18', () => { ReactDOM.hydrateRoot(safeQuerySelector('#root'), ) }) - expect((console.error: any).mock.calls).toMatchInlineSnapshot(` - Array [ - Array [ - "Warning: Prop \`%s\` did not match. Server: %s Client: %s%s", - "id", - "\\"R:2\\"", - "\\"R:0\\"", - " - at div - at className (/home/eps1lon/Development/forks/emotion/packages/react/__tests__/rehydration.js:639:57) - at Styled(DivWithId) (/home/eps1lon/Development/forks/emotion/packages/react/src/context.js:38:19)", - ], - ] - `) + expect((console.error: any).mock.calls).toMatchInlineSnapshot(`Array []`) expect((console.warn: any).mock.calls).toMatchInlineSnapshot(`Array []`) }) }) diff --git a/packages/styled/src/base.js b/packages/styled/src/base.js index 292ecaad6..3804e88d3 100644 --- a/packages/styled/src/base.js +++ b/packages/styled/src/base.js @@ -132,6 +132,7 @@ let createStyled: CreateStyled = (tag: any, options?: StyledOptions) => { newProps.ref = ref const ele = React.createElement(finalTag, newProps) + let possiblyStyleElement = <> if (!isBrowser && rules !== undefined) { let serializedNames = serialized.name let next = serialized.next @@ -139,20 +140,23 @@ let createStyled: CreateStyled = (tag: any, options?: StyledOptions) => { serializedNames += ' ' + next.name next = next.next } - return ( - <> -