Fix className hydration for <Transition appear> (#2390)
* Fix `className` hydration for `<Transition appear>` * Update changelog
This commit is contained in:
@@ -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([
|
||||
|
||||
Reference in New Issue
Block a user