Skip to content

Commit e819c0a

Browse files
authored
General/random internal cleanup (part 1) (#1484)
* 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
1 parent d200be5 commit e819c0a

File tree

18 files changed

+1058
-1213
lines changed

18 files changed

+1058
-1213
lines changed

packages/@headlessui-react/src/components/combobox/combobox.tsx

Lines changed: 503 additions & 585 deletions
Large diffs are not rendered by default.

packages/@headlessui-react/src/components/description/description.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, {
22
createContext,
3-
useCallback,
43
useContext,
54
useMemo,
65
useState,
@@ -16,6 +15,7 @@ import { useId } from '../../hooks/use-id'
1615
import { forwardRefWithAs, render } from '../../utils/render'
1716
import { useIsoMorphicEffect } from '../../hooks/use-iso-morphic-effect'
1817
import { useSyncRefs } from '../../hooks/use-sync-refs'
18+
import { useEvent } from '../../hooks/use-event'
1919

2020
// ---
2121

@@ -58,7 +58,7 @@ export function useDescriptions(): [
5858
// The provider component
5959
useMemo(() => {
6060
return function DescriptionProvider(props: DescriptionProviderProps) {
61-
let register = useCallback((value: string) => {
61+
let register = useEvent((value: string) => {
6262
setDescriptionIds((existing) => [...existing, value])
6363

6464
return () =>
@@ -68,7 +68,7 @@ export function useDescriptions(): [
6868
if (idx !== -1) clone.splice(idx, 1)
6969
return clone
7070
})
71-
}, [])
71+
})
7272

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

packages/@headlessui-react/src/components/dialog/dialog.tsx

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// WAI-ARIA: https://www.w3.org/TR/wai-aria-practices-1.2/#dialog_modal
22
import React, {
33
createContext,
4-
useCallback,
4+
createRef,
55
useContext,
66
useEffect,
77
useMemo,
@@ -15,7 +15,6 @@ import React, {
1515
MouseEvent as ReactMouseEvent,
1616
MutableRefObject,
1717
Ref,
18-
createRef,
1918
} from 'react'
2019

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

4242
enum DialogStates {
4343
Open,
@@ -184,12 +184,9 @@ let DialogRoot = forwardRefWithAs(function Dialog<
184184
panelRef: createRef(),
185185
} as StateDefinition)
186186

187-
let close = useCallback(() => onClose(false), [onClose])
187+
let close = useEvent(() => onClose(false))
188188

189-
let setTitleId = useCallback(
190-
(id: string | null) => dispatch({ type: ActionTypes.SetTitleId, id }),
191-
[dispatch]
192-
)
189+
let setTitleId = useEvent((id: string | null) => dispatch({ type: ActionTypes.SetTitleId, id }))
193190

194191
let ready = useServerHandoffComplete()
195192
let enabled = ready ? (__demoMode ? false : dialogState === DialogStates.Open) : false
@@ -323,7 +320,7 @@ let DialogRoot = forwardRefWithAs(function Dialog<
323320
<StackProvider
324321
type="Dialog"
325322
element={internalDialogRef}
326-
onUpdate={useCallback((message, type, element) => {
323+
onUpdate={useEvent((message, type, element) => {
327324
if (type !== 'Dialog') return
328325

329326
match(message, {
@@ -336,7 +333,7 @@ let DialogRoot = forwardRefWithAs(function Dialog<
336333
setNestedDialogCount((count) => count - 1)
337334
},
338335
})
339-
}, [])}
336+
})}
340337
>
341338
<ForcePortalRoot force={true}>
342339
<Portal>
@@ -393,16 +390,13 @@ let Overlay = forwardRefWithAs(function Overlay<
393390

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

396-
let handleClick = useCallback(
397-
(event: ReactMouseEvent) => {
398-
if (event.target !== event.currentTarget) return
399-
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
400-
event.preventDefault()
401-
event.stopPropagation()
402-
close()
403-
},
404-
[close]
405-
)
393+
let handleClick = useEvent((event: ReactMouseEvent) => {
394+
if (event.target !== event.currentTarget) return
395+
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
396+
event.preventDefault()
397+
event.stopPropagation()
398+
close()
399+
})
406400

407401
let slot = useMemo<OverlayRenderPropArg>(
408402
() => ({ open: dialogState === DialogStates.Open }),

packages/@headlessui-react/src/components/disclosure/disclosure.tsx

Lines changed: 52 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@
22
import React, {
33
Fragment,
44
createContext,
5-
useCallback,
65
useContext,
76
useEffect,
87
useMemo,
98
useReducer,
109
useRef,
1110

1211
// Types
12+
ContextType,
1313
Dispatch,
1414
ElementType,
1515
KeyboardEvent as ReactKeyboardEvent,
1616
MouseEvent as ReactMouseEvent,
17-
Ref,
1817
MutableRefObject,
19-
ContextType,
18+
Ref,
2019
} from 'react'
2120

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

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

191-
let close = useCallback(
192-
(focusableElement?: HTMLElement | MutableRefObject<HTMLElement | null>) => {
193-
dispatch({ type: ActionTypes.CloseDisclosure })
194-
let ownerDocument = getOwnerDocument(internalDisclosureRef)
195-
if (!ownerDocument) return
191+
let close = useEvent((focusableElement?: HTMLElement | MutableRefObject<HTMLElement | null>) => {
192+
dispatch({ type: ActionTypes.CloseDisclosure })
193+
let ownerDocument = getOwnerDocument(internalDisclosureRef)
194+
if (!ownerDocument) return
196195

197-
let restoreElement = (() => {
198-
if (!focusableElement) return ownerDocument.getElementById(buttonId)
199-
if (focusableElement instanceof HTMLElement) return focusableElement
200-
if (focusableElement.current instanceof HTMLElement) return focusableElement.current
196+
let restoreElement = (() => {
197+
if (!focusableElement) return ownerDocument.getElementById(buttonId)
198+
if (focusableElement instanceof HTMLElement) return focusableElement
199+
if (focusableElement.current instanceof HTMLElement) return focusableElement.current
201200

202-
return ownerDocument.getElementById(buttonId)
203-
})()
201+
return ownerDocument.getElementById(buttonId)
202+
})()
204203

205-
restoreElement?.focus()
206-
},
207-
[dispatch, buttonId]
208-
)
204+
restoreElement?.focus()
205+
})
209206

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

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

268-
let handleKeyDown = useCallback(
269-
(event: ReactKeyboardEvent<HTMLButtonElement>) => {
270-
if (isWithinPanel) {
271-
if (state.disclosureState === DisclosureStates.Closed) return
272-
273-
switch (event.key) {
274-
case Keys.Space:
275-
case Keys.Enter:
276-
event.preventDefault()
277-
event.stopPropagation()
278-
dispatch({ type: ActionTypes.ToggleDisclosure })
279-
state.buttonRef.current?.focus()
280-
break
281-
}
282-
} else {
283-
switch (event.key) {
284-
case Keys.Space:
285-
case Keys.Enter:
286-
event.preventDefault()
287-
event.stopPropagation()
288-
dispatch({ type: ActionTypes.ToggleDisclosure })
289-
break
290-
}
265+
let handleKeyDown = useEvent((event: ReactKeyboardEvent<HTMLButtonElement>) => {
266+
if (isWithinPanel) {
267+
if (state.disclosureState === DisclosureStates.Closed) return
268+
269+
switch (event.key) {
270+
case Keys.Space:
271+
case Keys.Enter:
272+
event.preventDefault()
273+
event.stopPropagation()
274+
dispatch({ type: ActionTypes.ToggleDisclosure })
275+
state.buttonRef.current?.focus()
276+
break
291277
}
292-
},
293-
[dispatch, isWithinPanel, state.disclosureState, state.buttonRef]
294-
)
278+
} else {
279+
switch (event.key) {
280+
case Keys.Space:
281+
case Keys.Enter:
282+
event.preventDefault()
283+
event.stopPropagation()
284+
dispatch({ type: ActionTypes.ToggleDisclosure })
285+
break
286+
}
287+
}
288+
})
295289

296-
let handleKeyUp = useCallback((event: ReactKeyboardEvent<HTMLButtonElement>) => {
290+
let handleKeyUp = useEvent((event: ReactKeyboardEvent<HTMLButtonElement>) => {
297291
switch (event.key) {
298292
case Keys.Space:
299293
// Required for firefox, event.preventDefault() in handleKeyDown for
@@ -302,22 +296,19 @@ let Button = forwardRefWithAs(function Button<TTag extends ElementType = typeof
302296
event.preventDefault()
303297
break
304298
}
305-
}, [])
306-
307-
let handleClick = useCallback(
308-
(event: ReactMouseEvent) => {
309-
if (isDisabledReactIssue7711(event.currentTarget)) return
310-
if (props.disabled) return
311-
312-
if (isWithinPanel) {
313-
dispatch({ type: ActionTypes.ToggleDisclosure })
314-
state.buttonRef.current?.focus()
315-
} else {
316-
dispatch({ type: ActionTypes.ToggleDisclosure })
317-
}
318-
},
319-
[dispatch, props.disabled, state.buttonRef, isWithinPanel]
320-
)
299+
})
300+
301+
let handleClick = useEvent((event: ReactMouseEvent) => {
302+
if (isDisabledReactIssue7711(event.currentTarget)) return
303+
if (props.disabled) return
304+
305+
if (isWithinPanel) {
306+
dispatch({ type: ActionTypes.ToggleDisclosure })
307+
state.buttonRef.current?.focus()
308+
} else {
309+
dispatch({ type: ActionTypes.ToggleDisclosure })
310+
}
311+
})
321312

322313
let slot = useMemo<ButtonRenderPropArg>(
323314
() => ({ open: state.disclosureState === DisclosureStates.Open }),

packages/@headlessui-react/src/components/focus-trap/focus-trap.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, {
2-
useRef,
32
useEffect,
3+
useRef,
44

55
// Types
66
ElementType,

packages/@headlessui-react/src/components/label/label.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, {
22
createContext,
3-
useCallback,
43
useContext,
54
useMemo,
65
useState,
@@ -16,6 +15,7 @@ import { useId } from '../../hooks/use-id'
1615
import { forwardRefWithAs, render } from '../../utils/render'
1716
import { useIsoMorphicEffect } from '../../hooks/use-iso-morphic-effect'
1817
import { useSyncRefs } from '../../hooks/use-sync-refs'
18+
import { useEvent } from '../../hooks/use-event'
1919

2020
// ---
2121

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

5959
return () =>
@@ -63,7 +63,7 @@ export function useLabels(): [string | undefined, (props: LabelProviderProps) =>
6363
if (idx !== -1) clone.splice(idx, 1)
6464
return clone
6565
})
66-
}, [])
66+
})
6767

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

0 commit comments

Comments
 (0)