Skip to content

Commit

Permalink
refactor: replace useForwardedRef with useImperativeHandle (#6830)
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Jun 10, 2024
1 parent 293e7d1 commit 23bac62
Show file tree
Hide file tree
Showing 16 changed files with 774 additions and 764 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"check:format": "prettier . --check",
"check:lint": "turbo run lint --continue -- --quiet",
"check:react-exhaustive-deps": "turbo run lint --continue -- --quiet --rule 'react-hooks/exhaustive-deps: [error, {additionalHooks: \"(useAsync|useMemoObservable|useObservableCallback)\"}]'",
"check:react-compiler": "eslint --no-inline-config --no-eslintrc --ext .cjs,.mjs,.js,.jsx,.ts,.tsx --parser @typescript-eslint/parser --plugin react-compiler --rule 'react-compiler/react-compiler: [warn]' --ignore-path .eslintignore.react-compiler --max-warnings 38 .",
"check:react-compiler": "eslint --no-inline-config --no-eslintrc --ext .cjs,.mjs,.js,.jsx,.ts,.tsx --parser @typescript-eslint/parser --plugin react-compiler --rule 'react-compiler/react-compiler: [warn]' --ignore-path .eslintignore.react-compiler --max-warnings 36 .",
"check:test": "run-s test -- --silent",
"check:types": "tsc && turbo run check:types --filter='./packages/*' --filter='./packages/@sanity/*'",
"chore:format:fix": "prettier --cache --write .",
Expand Down Expand Up @@ -157,7 +157,7 @@
"minimist": "^1.2.5",
"npm-run-all": "^4.1.5",
"ora": "^6.3.1",
"prettier": "^3.2.5",
"prettier": "^3.3.0",
"rimraf": "^3.0.2",
"rxjs": "^7.8.1",
"sanity": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/@sanity/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"groq-js": "^1.9.0",
"node-machine-id": "^1.1.12",
"pkg-dir": "^5.0.0",
"prettier": "^3.2.5",
"prettier": "^3.3.0",
"semver": "^7.3.5",
"silver-fleece": "1.1.0",
"validate-npm-package-name": "^3.0.0"
Expand Down
7 changes: 5 additions & 2 deletions packages/@sanity/portable-text-editor/src/editor/Editable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
type TextareaHTMLAttributes,
useCallback,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
Expand Down Expand Up @@ -59,7 +60,6 @@ import {normalizeSelection} from '../utils/selection'
import {fromSlateValue, isEqualToEmptyEditor, toSlateValue} from '../utils/values'
import {Element} from './components/Element'
import {Leaf} from './components/Leaf'
import {useForwardedRef} from './hooks/useForwardedRef'
import {usePortableTextEditor} from './hooks/usePortableTextEditor'
import {usePortableTextEditorKeyGenerator} from './hooks/usePortableTextEditorKeyGenerator'
import {usePortableTextEditorReadOnlyStatus} from './hooks/usePortableTextReadOnly'
Expand Down Expand Up @@ -140,12 +140,15 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
const portableTextEditor = usePortableTextEditor()
const readOnly = usePortableTextEditorReadOnlyStatus()
const keyGenerator = usePortableTextEditorKeyGenerator()
const ref = useForwardedRef(forwardedRef)
const ref = useRef<HTMLDivElement | null>(null)
const [editableElement, setEditableElement] = useState<HTMLDivElement | null>(null)
const [hasInvalidValue, setHasInvalidValue] = useState(false)
const [rangeDecorationState, setRangeDecorationsState] =
useState<BaseRangeWithDecoration[]>(EMPTY_DECORATIONS_STATE)

// Forward ref to parent component
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)

const rangeDecorationsRef = useRef(rangeDecorations)

const {change$, schemaTypes} = portableTextEditor
Expand Down

This file was deleted.

16 changes: 9 additions & 7 deletions packages/sanity/src/core/components/scroll/scrollContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {useForwardedRef} from '@sanity/ui'
import createPubSub from 'nano-pubsub'
import {
createElement,
Expand All @@ -8,7 +7,9 @@ import {
type HTMLProps,
useContext,
useEffect,
useImperativeHandle,
useMemo,
useRef,
} from 'react'
import {ScrollContext} from 'sanity/_singletons'

Expand All @@ -32,12 +33,13 @@ const noop = () => undefined
*/
export const ScrollContainer = forwardRef(function ScrollContainer<T extends ElementType = 'div'>(
props: ScrollContainerProps<T>,
ref: ForwardedRef<HTMLDivElement>,
forwardedRef: ForwardedRef<HTMLDivElement>,
) {
const {as = 'div', onScroll, ...rest} = props
const forwardedRef = useForwardedRef(ref)
const ref = useRef<HTMLDivElement | null>(null)

useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)

// const selfRef = useRef<HTMLElement | null>(null)
const parentContext = useContext(ScrollContext)
const childContext = useMemo(() => createPubSub<Event>(), [])

Expand All @@ -62,7 +64,7 @@ export const ScrollContainer = forwardRef(function ScrollContainer<T extends Ele
childContext.publish(event)
}

const el = forwardedRef.current
const el = ref.current

if (!el) {
return undefined
Expand All @@ -76,11 +78,11 @@ export const ScrollContainer = forwardRef(function ScrollContainer<T extends Ele
return () => {
el.removeEventListener('scroll', handleScroll)
}
}, [childContext, forwardedRef])
}, [childContext, ref])

return (
<ScrollContext.Provider value={childContext}>
{createElement(as, {'ref': forwardedRef, 'data-testid': 'scroll-container', ...rest})}
{createElement(as, {'ref': ref, 'data-testid': 'scroll-container', ...rest})}
</ScrollContext.Provider>
)
})
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
/* eslint-disable camelcase */
import {type DeprecatedProperty, type FormNodeValidation} from '@sanity/types'
import {Badge, Box, Flex, Stack, Text, type Theme, useForwardedRef} from '@sanity/ui'
import {Badge, Box, Flex, Stack, Text, type Theme} from '@sanity/ui'
import {
type FocusEvent,
type ForwardedRef,
forwardRef,
type HTMLProps,
type ReactNode,
useCallback,
useImperativeHandle,
useMemo,
useRef,
} from 'react'
import {css, styled} from 'styled-components'

Expand Down Expand Up @@ -107,7 +109,7 @@ const EMPTY_ARRAY: never[] = []
/** @internal */
export const FormFieldSet = forwardRef(function FormFieldSet(
props: FormFieldSetProps & Omit<HTMLProps<HTMLDivElement>, 'as' | 'height' | 'ref'>,
ref: ForwardedRef<HTMLDivElement>,
forwardedRef: ForwardedRef<HTMLDivElement>,
) {
const {
__internal_comments: comments,
Expand All @@ -134,18 +136,20 @@ export const FormFieldSet = forwardRef(function FormFieldSet(
const {focused, hovered, onMouseEnter, onMouseLeave} = useFieldActions()

const hasValidationMarkers = validation.length > 0
const forwardedRef = useForwardedRef(ref)
const ref = useRef<HTMLDivElement | null>(null)
const {t} = useTranslation()

useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)

const handleFocus = useCallback(
(event: FocusEvent<HTMLDivElement>) => {
const element = forwardedRef.current
const element = ref.current

if (element === event.target) {
if (onFocus) onFocus(event)
}
},
[forwardedRef, onFocus],
[onFocus],
)

const handleToggle = useCallback(
Expand Down Expand Up @@ -224,7 +228,7 @@ export const FormFieldSet = forwardRef(function FormFieldSet(
hidden={collapsed}
paddingLeft={level === 0 ? 0 : 3}
onFocus={typeof tabIndex === 'number' && tabIndex > -1 ? handleFocus : undefined}
ref={forwardedRef}
ref={ref}
tabIndex={tabIndex}
>
{!collapsed && content}
Expand Down
38 changes: 20 additions & 18 deletions packages/sanity/src/core/form/components/tagInput/tagInput.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {CloseIcon} from '@sanity/icons'
import {Box, Card, Flex, isHTMLElement, rem, Text, type Theme, useForwardedRef} from '@sanity/ui'
import {Box, Card, Flex, isHTMLElement, rem, Text, type Theme} from '@sanity/ui'
import {
type ChangeEvent,
type FocusEvent,
forwardRef,
type HTMLProps,
type KeyboardEvent,
type PointerEvent,
type Ref,
useCallback,
useEffect,
useImperativeHandle,
useRef,
useState,
} from 'react'
Expand Down Expand Up @@ -147,7 +147,7 @@ export const TagInput = forwardRef(
placeholder?: string
value?: {value: string}[]
} & Omit<HTMLProps<HTMLInputElement>, 'as' | 'onChange' | 'onFocus' | 'ref' | 'value'>,
ref: Ref<HTMLInputElement>,
forwardedRef: React.ForwardedRef<HTMLInputElement>,
) => {
const {
disabled,
Expand All @@ -163,23 +163,25 @@ export const TagInput = forwardRef(
const [inputValue, setInputValue] = useState('')
const enabled = !disabled && !readOnly
const [focused, setFocused] = useState(false)
const forwardedRef = useForwardedRef(ref)
const ref = useRef<HTMLInputElement | null>(null)
const rootRef = useRef<HTMLDivElement | null>(null)

const handleRootPointerDown = useCallback(
(event: PointerEvent<HTMLDivElement>) => {
const isTagElement = isHTMLElement(event.target) && event.target.closest('[data-ui="Tag"]')
useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(
forwardedRef,
() => ref.current,
)

if (isTagElement) return
const handleRootPointerDown = useCallback((event: PointerEvent<HTMLDivElement>) => {
const isTagElement = isHTMLElement(event.target) && event.target.closest('[data-ui="Tag"]')

const inputElement = forwardedRef.current
if (isTagElement) return

if (inputElement) {
setTimeout(() => inputElement.focus(), 0)
}
},
[forwardedRef],
)
const inputElement = ref.current

if (inputElement) {
setTimeout(() => inputElement.focus(), 0)
}
}, [])

const handleInputBlur = useCallback(() => {
setFocused(false)
Expand Down Expand Up @@ -229,13 +231,13 @@ export const TagInput = forwardRef(
)

useEffect(() => {
const inputElement = forwardedRef.current
const inputElement = ref.current

if (inputElement) {
inputElement.style.width = '0'
inputElement.style.width = `${inputElement.scrollWidth}px`
}
}, [forwardedRef, inputValue])
}, [inputValue])

return (
<Root
Expand Down Expand Up @@ -285,7 +287,7 @@ export const TagInput = forwardRef(
onChange={handleInputChange}
onFocus={handleInputFocus}
onKeyDown={handleInputKeyDown}
ref={forwardedRef}
ref={ref}
type="text"
value={inputValue}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/* eslint-disable no-nested-ternary */

import {TextInput, useForwardedRef} from '@sanity/ui'
import {TextInput} from '@sanity/ui'
import {
type FocusEvent,
type ForwardedRef,
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useRef,
useState,
} from 'react'

Expand Down Expand Up @@ -34,7 +36,7 @@ const DEFAULT_PLACEHOLDER_TIME = new Date()

export const CommonDateTimeInput = forwardRef(function CommonDateTimeInput(
props: CommonDateTimeInputProps,
ref: ForwardedRef<HTMLInputElement>,
forwardedRef: ForwardedRef<HTMLInputElement>,
) {
const {
id,
Expand Down Expand Up @@ -88,7 +90,12 @@ export const CommonDateTimeInput = forwardRef(function CommonDateTimeInput(
[serialize, onChange],
)

const forwardedRef = useForwardedRef(ref)
const ref = useRef<HTMLInputElement | null>(null)

useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(
forwardedRef,
() => ref.current,
)

const parseResult = localValue ? parseInputValue(localValue) : value ? deserialize(value) : null

Expand All @@ -113,7 +120,7 @@ export const CommonDateTimeInput = forwardRef(function CommonDateTimeInput(
example: formatInputValue(DEFAULT_PLACEHOLDER_TIME),
})
}
ref={forwardedRef}
ref={ref}
value={parseResult?.date}
inputValue={inputValue || ''}
readOnly={Boolean(readOnly)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {CalendarIcon} from '@sanity/icons'
import {Box, Flex, LayerProvider, useClickOutside, useForwardedRef} from '@sanity/ui'
import {Box, Flex, LayerProvider, useClickOutside} from '@sanity/ui'
import {
type FocusEvent,
type ForwardedRef,
forwardRef,
type KeyboardEvent,
useCallback,
useImperativeHandle,
useRef,
useState,
} from 'react'
Expand All @@ -32,7 +33,7 @@ export interface DateTimeInputProps {

export const DateTimeInput = forwardRef(function DateTimeInput(
props: DateTimeInputProps,
ref: ForwardedRef<HTMLInputElement>,
forwardedRef: ForwardedRef<HTMLInputElement>,
) {
const {
value,
Expand All @@ -45,17 +46,22 @@ export const DateTimeInput = forwardRef(function DateTimeInput(
...rest
} = props
const [popoverRef, setPopoverRef] = useState<HTMLElement | null>(null)
const forwardedRef = useForwardedRef(ref)
const ref = useRef<HTMLInputElement | null>(null)
const buttonRef = useRef(null)

useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(
forwardedRef,
() => ref.current,
)

const [isPickerOpen, setPickerOpen] = useState(false)

useClickOutside(() => setPickerOpen(false), [popoverRef])

const handleDeactivation = useCallback(() => {
forwardedRef.current?.focus()
forwardedRef.current?.select()
}, [forwardedRef])
ref.current?.focus()
ref.current?.select()
}, [])

const handleKeyUp = useCallback((e: KeyboardEvent<HTMLDivElement>) => {
if (e.key === 'Escape') {
Expand All @@ -81,7 +87,7 @@ export const DateTimeInput = forwardRef(function DateTimeInput(

return (
<LazyTextInput
ref={forwardedRef}
ref={ref}
{...rest}
value={inputValue}
onChange={onInputChange}
Expand Down
Loading

0 comments on commit 23bac62

Please sign in to comment.