Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(styled): Ensure no hydration mismatch with React.useId #2542

Merged
merged 14 commits into from Nov 14, 2021
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -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",
Expand Down
72 changes: 72 additions & 0 deletions packages/react/__tests__/rehydration.js
Expand Up @@ -17,6 +17,7 @@ let ReactDOMServer
let createCache
let css
let jsx
let styled
let CacheProvider
let Global
let createEmotionServer
Expand All @@ -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 => {
Expand Down Expand Up @@ -592,3 +594,73 @@ test('duplicated global styles can be removed safely after rehydrating HTML SSRe
</head>
`)
})

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')
})
Comment on lines +607 to +616
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

neat


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 <div className={className} id={id} />
})({
border: '1px solid black'
})

return ReactDOMServer.renderToString(<StyledDivWithId />)
})

safeQuerySelector('body').innerHTML = `<div id="root">${finalHTML}</div>`

resetAllModules()

const StyledDivWithId = styled(function DivWithId({ className }) {
const id = (React: any).useId()
return <div className={className} id={id} />
})({
border: '1px solid black'
})

;(React: any).unstable_act(() => {
ReactDOM.hydrateRoot(safeQuerySelector('#root'), <StyledDivWithId />)
})

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 []`)
})
})
25 changes: 25 additions & 0 deletions yarn.lock
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down