Skip to content

Commit

Permalink
General/random internal cleanup (part 1) (#1484)
Browse files Browse the repository at this point in the history
* sort React imports

* improve type signature of the `useEvent` hook

* use more correct `useIsoMorphicEffect` check in `useEvent`

* refactor `useCallback` to cleaner `useEvent`

* convert `const` to `let`

Just for consistency..

* cleanup `Tabs` code

Created explicit functions that can be called from child components
instead of calling `dispatch` directly. Introduced a `useData` and
`useActions` hook to make child components easier.

The seperation of `useData` allows us to pass down props directly
instead of going via the `useReducer` hook and dispatching actions to
make values up to date.

* cleanup `Combobox` code

* cleanup `RadioGroup` code
  • Loading branch information
RobinMalfait committed May 23, 2022
1 parent d200be5 commit e819c0a
Show file tree
Hide file tree
Showing 18 changed files with 1,058 additions and 1,213 deletions.
1,088 changes: 503 additions & 585 deletions packages/@headlessui-react/src/components/combobox/combobox.tsx

Large diffs are not rendered by default.

@@ -1,6 +1,5 @@
import React, {
createContext,
useCallback,
useContext,
useMemo,
useState,
Expand All @@ -16,6 +15,7 @@ import { useId } from '../../hooks/use-id'
import { forwardRefWithAs, render } from '../../utils/render'
import { useIsoMorphicEffect } from '../../hooks/use-iso-morphic-effect'
import { useSyncRefs } from '../../hooks/use-sync-refs'
import { useEvent } from '../../hooks/use-event'

// ---

Expand Down Expand Up @@ -58,7 +58,7 @@ export function useDescriptions(): [
// The provider component
useMemo(() => {
return function DescriptionProvider(props: DescriptionProviderProps) {
let register = useCallback((value: string) => {
let register = useEvent((value: string) => {
setDescriptionIds((existing) => [...existing, value])

return () =>
Expand All @@ -68,7 +68,7 @@ export function useDescriptions(): [
if (idx !== -1) clone.splice(idx, 1)
return clone
})
}, [])
})

let contextBag = useMemo(
() => ({ register, slot: props.slot, name: props.name, props: props.props }),
Expand Down
32 changes: 13 additions & 19 deletions packages/@headlessui-react/src/components/dialog/dialog.tsx
@@ -1,7 +1,7 @@
// WAI-ARIA: https://www.w3.org/TR/wai-aria-practices-1.2/#dialog_modal
import React, {
createContext,
useCallback,
createRef,
useContext,
useEffect,
useMemo,
Expand All @@ -15,7 +15,6 @@ import React, {
MouseEvent as ReactMouseEvent,
MutableRefObject,
Ref,
createRef,
} from 'react'

import { Props } from '../../types'
Expand All @@ -38,6 +37,7 @@ import { getOwnerDocument } from '../../utils/owner'
import { useOwnerDocument } from '../../hooks/use-owner'
import { useEventListener } from '../../hooks/use-event-listener'
import { Hidden, Features as HiddenFeatures } from '../../internal/hidden'
import { useEvent } from '../../hooks/use-event'

enum DialogStates {
Open,
Expand Down Expand Up @@ -184,12 +184,9 @@ let DialogRoot = forwardRefWithAs(function Dialog<
panelRef: createRef(),
} as StateDefinition)

let close = useCallback(() => onClose(false), [onClose])
let close = useEvent(() => onClose(false))

let setTitleId = useCallback(
(id: string | null) => dispatch({ type: ActionTypes.SetTitleId, id }),
[dispatch]
)
let setTitleId = useEvent((id: string | null) => dispatch({ type: ActionTypes.SetTitleId, id }))

let ready = useServerHandoffComplete()
let enabled = ready ? (__demoMode ? false : dialogState === DialogStates.Open) : false
Expand Down Expand Up @@ -323,7 +320,7 @@ let DialogRoot = forwardRefWithAs(function Dialog<
<StackProvider
type="Dialog"
element={internalDialogRef}
onUpdate={useCallback((message, type, element) => {
onUpdate={useEvent((message, type, element) => {
if (type !== 'Dialog') return

match(message, {
Expand All @@ -336,7 +333,7 @@ let DialogRoot = forwardRefWithAs(function Dialog<
setNestedDialogCount((count) => count - 1)
},
})
}, [])}
})}
>
<ForcePortalRoot force={true}>
<Portal>
Expand Down Expand Up @@ -393,16 +390,13 @@ let Overlay = forwardRefWithAs(function Overlay<

let id = `headlessui-dialog-overlay-${useId()}`

let handleClick = useCallback(
(event: ReactMouseEvent) => {
if (event.target !== event.currentTarget) return
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
event.preventDefault()
event.stopPropagation()
close()
},
[close]
)
let handleClick = useEvent((event: ReactMouseEvent) => {
if (event.target !== event.currentTarget) return
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
event.preventDefault()
event.stopPropagation()
close()
})

let slot = useMemo<OverlayRenderPropArg>(
() => ({ open: dialogState === DialogStates.Open }),
Expand Down
113 changes: 52 additions & 61 deletions packages/@headlessui-react/src/components/disclosure/disclosure.tsx
Expand Up @@ -2,21 +2,20 @@
import React, {
Fragment,
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useReducer,
useRef,

// Types
ContextType,
Dispatch,
ElementType,
KeyboardEvent as ReactKeyboardEvent,
MouseEvent as ReactMouseEvent,
Ref,
MutableRefObject,
ContextType,
Ref,
} from 'react'

import { Props } from '../../types'
Expand All @@ -29,6 +28,7 @@ import { isDisabledReactIssue7711 } from '../../utils/bugs'
import { OpenClosedProvider, State, useOpenClosed } from '../../internal/open-closed'
import { useResolveButtonType } from '../../hooks/use-resolve-button-type'
import { getOwnerDocument } from '../../utils/owner'
import { useEvent } from '../../hooks/use-event'

enum DisclosureStates {
Open,
Expand Down Expand Up @@ -188,24 +188,21 @@ let DisclosureRoot = forwardRefWithAs(function Disclosure<
useEffect(() => dispatch({ type: ActionTypes.SetButtonId, buttonId }), [buttonId, dispatch])
useEffect(() => dispatch({ type: ActionTypes.SetPanelId, panelId }), [panelId, dispatch])

let close = useCallback(
(focusableElement?: HTMLElement | MutableRefObject<HTMLElement | null>) => {
dispatch({ type: ActionTypes.CloseDisclosure })
let ownerDocument = getOwnerDocument(internalDisclosureRef)
if (!ownerDocument) return
let close = useEvent((focusableElement?: HTMLElement | MutableRefObject<HTMLElement | null>) => {
dispatch({ type: ActionTypes.CloseDisclosure })
let ownerDocument = getOwnerDocument(internalDisclosureRef)
if (!ownerDocument) return

let restoreElement = (() => {
if (!focusableElement) return ownerDocument.getElementById(buttonId)
if (focusableElement instanceof HTMLElement) return focusableElement
if (focusableElement.current instanceof HTMLElement) return focusableElement.current
let restoreElement = (() => {
if (!focusableElement) return ownerDocument.getElementById(buttonId)
if (focusableElement instanceof HTMLElement) return focusableElement
if (focusableElement.current instanceof HTMLElement) return focusableElement.current

return ownerDocument.getElementById(buttonId)
})()
return ownerDocument.getElementById(buttonId)
})()

restoreElement?.focus()
},
[dispatch, buttonId]
)
restoreElement?.focus()
})

let api = useMemo<ContextType<typeof DisclosureAPIContext>>(() => ({ close }), [close])

Expand Down Expand Up @@ -265,35 +262,32 @@ let Button = forwardRefWithAs(function Button<TTag extends ElementType = typeof
let internalButtonRef = useRef<HTMLButtonElement | null>(null)
let buttonRef = useSyncRefs(internalButtonRef, ref, !isWithinPanel ? state.buttonRef : null)

let handleKeyDown = useCallback(
(event: ReactKeyboardEvent<HTMLButtonElement>) => {
if (isWithinPanel) {
if (state.disclosureState === DisclosureStates.Closed) return

switch (event.key) {
case Keys.Space:
case Keys.Enter:
event.preventDefault()
event.stopPropagation()
dispatch({ type: ActionTypes.ToggleDisclosure })
state.buttonRef.current?.focus()
break
}
} else {
switch (event.key) {
case Keys.Space:
case Keys.Enter:
event.preventDefault()
event.stopPropagation()
dispatch({ type: ActionTypes.ToggleDisclosure })
break
}
let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLButtonElement>) => {
if (isWithinPanel) {
if (state.disclosureState === DisclosureStates.Closed) return

switch (event.key) {
case Keys.Space:
case Keys.Enter:
event.preventDefault()
event.stopPropagation()
dispatch({ type: ActionTypes.ToggleDisclosure })
state.buttonRef.current?.focus()
break
}
},
[dispatch, isWithinPanel, state.disclosureState, state.buttonRef]
)
} else {
switch (event.key) {
case Keys.Space:
case Keys.Enter:
event.preventDefault()
event.stopPropagation()
dispatch({ type: ActionTypes.ToggleDisclosure })
break
}
}
})

let handleKeyUp = useCallback((event: ReactKeyboardEvent<HTMLButtonElement>) => {
let handleKeyUp = useEvent((event: ReactKeyboardEvent<HTMLButtonElement>) => {
switch (event.key) {
case Keys.Space:
// Required for firefox, event.preventDefault() in handleKeyDown for
Expand All @@ -302,22 +296,19 @@ let Button = forwardRefWithAs(function Button<TTag extends ElementType = typeof
event.preventDefault()
break
}
}, [])

let handleClick = useCallback(
(event: ReactMouseEvent) => {
if (isDisabledReactIssue7711(event.currentTarget)) return
if (props.disabled) return

if (isWithinPanel) {
dispatch({ type: ActionTypes.ToggleDisclosure })
state.buttonRef.current?.focus()
} else {
dispatch({ type: ActionTypes.ToggleDisclosure })
}
},
[dispatch, props.disabled, state.buttonRef, isWithinPanel]
)
})

let handleClick = useEvent((event: ReactMouseEvent) => {
if (isDisabledReactIssue7711(event.currentTarget)) return
if (props.disabled) return

if (isWithinPanel) {
dispatch({ type: ActionTypes.ToggleDisclosure })
state.buttonRef.current?.focus()
} else {
dispatch({ type: ActionTypes.ToggleDisclosure })
}
})

let slot = useMemo<ButtonRenderPropArg>(
() => ({ open: state.disclosureState === DisclosureStates.Open }),
Expand Down
@@ -1,6 +1,6 @@
import React, {
useRef,
useEffect,
useRef,

// Types
ElementType,
Expand Down
6 changes: 3 additions & 3 deletions packages/@headlessui-react/src/components/label/label.tsx
@@ -1,6 +1,5 @@
import React, {
createContext,
useCallback,
useContext,
useMemo,
useState,
Expand All @@ -16,6 +15,7 @@ import { useId } from '../../hooks/use-id'
import { forwardRefWithAs, render } from '../../utils/render'
import { useIsoMorphicEffect } from '../../hooks/use-iso-morphic-effect'
import { useSyncRefs } from '../../hooks/use-sync-refs'
import { useEvent } from '../../hooks/use-event'

// ---

Expand Down Expand Up @@ -53,7 +53,7 @@ export function useLabels(): [string | undefined, (props: LabelProviderProps) =>
// The provider component
useMemo(() => {
return function LabelProvider(props: LabelProviderProps) {
let register = useCallback((value: string) => {
let register = useEvent((value: string) => {
setLabelIds((existing) => [...existing, value])

return () =>
Expand All @@ -63,7 +63,7 @@ export function useLabels(): [string | undefined, (props: LabelProviderProps) =>
if (idx !== -1) clone.splice(idx, 1)
return clone
})
}, [])
})

let contextBag = useMemo(
() => ({ register, slot: props.slot, name: props.name, props: props.props }),
Expand Down

0 comments on commit e819c0a

Please sign in to comment.