Fix className hydration for <Transition appear> (#2390)

* Fix `className` hydration for `<Transition appear>`

* Update changelog
This commit is contained in:
Jordan Pittman
2023-03-22 11:41:09 -04:00
committed by GitHub
parent e814c5022d
commit f4e9710bca
5 changed files with 78 additions and 4 deletions
+1
View File
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix focus styles showing up when using the mouse ([#2347](https://github.com/tailwindlabs/headlessui/pull/2347))
- Fix "Can't perform a React state update on an unmounted component." when using the `Transition` component ([#2374](https://github.com/tailwindlabs/headlessui/pull/2374))
- Add `FocusTrap` event listeners once document has loaded ([#2389](https://github.com/tailwindlabs/headlessui/pull/2389))
- Fix `className` hydration for `<Transition appear>` ([#2390](https://github.com/tailwindlabs/headlessui/pull/2390))
### Added
@@ -9,8 +9,34 @@ beforeAll(() => {
describe('Rendering', () => {
describe('SSR', () => {
it('A transition without appear=true does not insert classes during SSR', async () => {
let result = await renderSSR(
<Transition
as={Fragment}
show={true}
enter="enter"
enterFrom="enter-from"
enterTo="enter-to"
>
<div className="inner"></div>
</Transition>
)
let div = document.querySelector('.inner')
expect(div).not.toBeNull()
expect(div?.className).toBe('inner')
await result.hydrate()
div = document.querySelector('.inner')
expect(div).not.toBeNull()
expect(div?.className).toBe('inner')
})
it('should not overwrite className of children when as=Fragment', async () => {
await renderSSR(
let result = await renderSSR(
<Transition
as={Fragment}
show={true}
@@ -27,6 +53,13 @@ describe('Rendering', () => {
expect(div).not.toBeNull()
expect(div?.className).toBe('inner enter enter-from')
await result.hydrate()
div = document.querySelector('.inner')
expect(div).not.toBeNull()
expect(div?.className).toBe('inner enter enter-from')
})
})
})
@@ -436,7 +436,7 @@ function TransitionChildFn<TTag extends ElementType = typeof DEFAULT_TRANSITION_
let theirProps = rest
let ourProps = { ref: transitionRef }
if (appear && show && env.isServer) {
if (appear && show) {
theirProps = {
...theirProps,
// Already apply the `enter` and `enterFrom` on the server if required
@@ -10,8 +10,41 @@ beforeAll(() => {
describe('Rendering', () => {
describe('SSR', () => {
it('A transition without appear=true does not insert classes during SSR', async () => {
let result = await renderSSR(
defineComponent({
components: Transition,
template: html`
<TransitionRoot
as="template"
:show="true"
enter="enter"
enterFrom="enter-from"
enterTo="enter-to"
>
<div class="inner"></div>
</TransitionRoot>
`,
})
)
let div = document.querySelector('.inner')
expect(div).not.toBeNull()
expect(div?.className).toBe('inner')
// If we don't await then we get the same for SSR and hydration
// but we want to investigate what effects this has on our other transition tests too
await result.hydrate()
div = document.querySelector('.inner')
expect(div).not.toBeNull()
expect(div?.className).toBe('inner enter enter-from')
})
it('should not overwrite className of children when as=Fragment', async () => {
await renderSSR(
let result = await renderSSR(
defineComponent({
components: Transition,
template: html`
@@ -33,6 +66,13 @@ describe('Rendering', () => {
expect(div).not.toBeNull()
expect(div?.className).toBe('inner enter enter-from')
await result.hydrate()
div = document.querySelector('.inner')
expect(div).not.toBeNull()
expect(div?.className).toBe('inner enter enter-from')
})
})
})
@@ -354,7 +354,7 @@ export let TransitionChild = defineComponent({
let ourProps = { ref: container }
let theirProps = {
...rest,
...(appear && show && env.isServer
...(appear.value && show.value && env.isServer
? {
// Already apply the `enter` and `enterFrom` on the server if required
class: normalizeClass([