Fix SSR support in Deno (#1671)

* check typeof document in addition to typeof window

* remove unused import

* Extract SSR check to a central spot

* Fix CS

* Update changelog

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This commit is contained in:
Sean Aye
2022-07-14 12:30:33 -04:00
committed by GitHub
parent 8c7d5ce8d2
commit 6119cc202d
12 changed files with 27 additions and 9 deletions
+4
View File
@@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `by` prop for `Listbox`, `Combobox` and `RadioGroup` ([#1482](https://github.com/tailwindlabs/headlessui/pull/1482))
- Add `@headlessui/tailwindcss` plugin ([#1487](https://github.com/tailwindlabs/headlessui/pull/1487))
### Fixed
- Fixed SSR support on Deno ([#1671](https://github.com/tailwindlabs/headlessui/pull/1671))
## [1.6.6] - 2022-07-07
### Fixed
@@ -21,6 +21,7 @@ import { useServerHandoffComplete } from '../../hooks/use-server-handoff-complet
import { optionalRef, useSyncRefs } from '../../hooks/use-sync-refs'
import { useOwnerDocument } from '../../hooks/use-owner'
import { microTask } from '../../utils/micro-task'
import { isServer } from '../../utils/ssr'
function usePortalTarget(ref: MutableRefObject<HTMLElement | null>): HTMLElement | null {
let forceInRoot = usePortalRoot()
@@ -33,7 +34,7 @@ function usePortalTarget(ref: MutableRefObject<HTMLElement | null>): HTMLElement
if (!forceInRoot && groupTarget !== null) return null
// No group context is used, let's create a default portal root
if (typeof window === 'undefined') return null
if (isServer) return null
let existingRoot = ownerDocument?.getElementById('headlessui-portal-root')
if (existingRoot) return existingRoot
@@ -81,7 +82,7 @@ let PortalRoot = forwardRefWithAs(function Portal<
let ownerDocument = useOwnerDocument(internalPortalRootRef)
let target = usePortalTarget(internalPortalRootRef)
let [element] = useState<HTMLDivElement | null>(() =>
typeof window === 'undefined' ? null : ownerDocument?.createElement('div') ?? null
isServer ? null : ownerDocument?.createElement('div') ?? null
)
let ready = useServerHandoffComplete()
@@ -1,3 +1,4 @@
import { useLayoutEffect, useEffect } from 'react'
import { isServer } from '../utils/ssr'
export let useIsoMorphicEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect
export let useIsoMorphicEffect = isServer ? useEffect : useLayoutEffect
@@ -1,9 +1,10 @@
import { MutableRefObject } from 'react'
import { isServer } from './ssr'
export function getOwnerDocument<T extends Element | MutableRefObject<Element | null>>(
element: T | null | undefined
) {
if (typeof window === 'undefined') return null
if (isServer) return null
if (element instanceof Node) return element.ownerDocument
if (element?.hasOwnProperty('current')) {
if (element.current instanceof Node) return element.current.ownerDocument
@@ -0,0 +1 @@
export const isServer = typeof window === 'undefined' || typeof document === 'undefined'
+4
View File
@@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `by` prop for `Listbox`, `Combobox` and `RadioGroup` ([#1482](https://github.com/tailwindlabs/headlessui/pull/1482))
- Add `@headlessui/tailwindcss` plugin ([#1487](https://github.com/tailwindlabs/headlessui/pull/1487))
### Fixed
- Fixed SSR support on Deno ([#1671](https://github.com/tailwindlabs/headlessui/pull/1671))
## [1.6.7] - 2022-07-12
### Fixed
@@ -1,4 +1,4 @@
import { ref, nextTick, onMounted } from 'vue'
import { ref, onMounted } from 'vue'
import { FocusTrap } from './focus-trap'
import { assertActiveElement, getByText } from '../../test-utils/accessibility-assertions'
@@ -1,4 +1,5 @@
import { watchEffect } from 'vue'
import { isServer } from '../utils/ssr'
export function useEventListener<TType extends keyof WindowEventMap>(
element: HTMLElement | Document | Window | EventTarget | null | undefined,
@@ -6,7 +7,7 @@ export function useEventListener<TType extends keyof WindowEventMap>(
listener: (event: WindowEventMap[TType]) => any,
options?: boolean | AddEventListenerOptions
) {
if (typeof window === 'undefined') return
if (isServer) return
watchEffect((onInvalidate) => {
element = element ?? window
@@ -1,11 +1,12 @@
import { watchEffect } from 'vue'
import { isServer } from '../utils/ssr'
export function useWindowEvent<TType extends keyof WindowEventMap>(
type: TType,
listener: (this: Window, ev: WindowEventMap[TType]) => any,
options?: boolean | AddEventListenerOptions
) {
if (typeof window === 'undefined') return
if (isServer) return
watchEffect((onInvalidate) => {
window.addEventListener(type, listener, options)
+2 -1
View File
@@ -1,10 +1,11 @@
import { Ref } from 'vue'
import { dom } from './dom'
import { isServer } from './ssr'
export function getOwnerDocument<T extends Element | Ref<Element | null>>(
element: T | null | undefined
) {
if (typeof window === 'undefined') return null
if (isServer) return null
if (element instanceof Node) return element.ownerDocument
if (element?.hasOwnProperty('value')) {
let domElement = dom(element)
@@ -0,0 +1 @@
export const isServer = typeof window === 'undefined' || typeof document === 'undefined'
@@ -20,7 +20,9 @@ let people = [
let locations = ['New York', 'London', 'Paris', 'Berlin']
export default function App() {
let [result, setResult] = useState(() => (typeof window === 'undefined' ? [] : new FormData()))
let [result, setResult] = useState(() =>
typeof window === 'undefined' || typeof document === 'undefined' ? [] : new FormData()
)
let [notifications, setNotifications] = useState(false)
let [apple, setApple] = useState(false)
let [banana, setBanana] = useState(false)