HextaUI

useComposedRef

Kendi öğenize bir ref tutarken, üst bileşenin ilettiği her ref'e de yönlendirmeyi sürdürür.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import { useComposedRef } from "@/hooks/use-composed-ref"

function CharacterInput({ ref, ...props }: React.ComponentProps<"input">) {
  const [inputRef, setRef] = useComposedRef<HTMLInputElement>(ref)
  const [length, setLength] = React.useState(0)

  return (
    <div className="flex h-9 w-full items-center gap-2 rounded-md bg-muted pe-3 focus-within:ring-3 focus-within:ring-focus-ring">
      <input
        ref={setRef}
        {...props}
        onChange={(event) => {
          props.onChange?.(event)
          setLength(event.target.value.length)
        }}
        className="h-full min-w-0 flex-1 bg-transparent ps-3 text-sm outline-none focus-visible:outline-hidden pointer-coarse:text-touch"
      />
      <button
        type="button"
        hidden={length === 0}
        onClick={() => {
          const input = inputRef.current
          if (input) {
            input.value = ""
            setLength(0)
            input.focus()
          }
        }}
        className="text-xs text-muted-foreground hover:text-foreground"
      >
        Clear
      </button>
    </div>
  )
}

export function UseComposedRefDemo() {
  const ref = React.useRef<HTMLInputElement>(null)

  return (
    <div className="flex w-full max-w-xs flex-col gap-3">
      <CharacterInput ref={ref} aria-label="Search" placeholder="Search" />
      <Button variant="outline" size="sm" onClick={() => ref.current?.focus()}>
        Focus from the parent
      </Button>
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/use-composed-ref.json

Hook'u ve bağımlı olduğu her şeyi projenize ekler.

import { useComposedRef } from "@/hooks/use-composed-ref"
function SearchInput({ ref, ...props }: React.ComponentProps<"input">) {
  const [inputRef, setRef] = useComposedRef<HTMLInputElement>(ref)

  React.useEffect(() => {
    inputRef.current?.select()
  }, [inputRef])

  return <input ref={setRef} {...props} />
}

React 19'da ref normal bir prop'tur. Bileşeniniz öğeye kendisi için de ihtiyaç duyduğunda iki ref'iniz ve tek bir ref niteliğiniz olur. Bu hook size okumak için bir nesne ref'i ve ikisini birden dolduran bir geri çağırma verir.

function SearchInput({ ref, ...props }: React.ComponentProps<"input">) {
  const inputRef = React.useRef<HTMLInputElement>(null)
  return <input ref={inputRef} {...props} />
}

Bu derlenir ama üst öğenin ref'i düşer, bu yüzden ref.current üst öğede null kalır. useComposedRef ile hem üst öğe hem bileşen öğeyi alır.

  • Döndürülen inputRef normal bir RefObject'tir; böylece useAutosize veya useInvalidShake gibi bir tane bekleyen hook'lara verebilirsiniz.
  • setRef, üst öğenin ref'i aynı kaldığı sürece aynı kimliği korur; böylece React onu her işlemede ayırıp yeniden bağlamaz.
  • Nesne ref'leri, geri çağırma ref'leri ve hiç ref olmamasıyla çalışır.

Tam olarak bir iletilen ref'i kendi nesne ref'inizle birleştirdiğinizde useComposedRef kullanın; çoğu bileşen budur. İkiden fazlasını birleştirdiğinizde, biri başka bir hook'tan gelen geri çağırma ref'iyse veya iletilen bir geri çağırma ref'i React 19 temizleme fonksiyonu döndürüyorsa useMergedRef kullanın. useComposedRef, ayrılırken bir geri çağırma ref'ini temizlemesini çalıştırmak yerine null ile çağırır.

PropTürVarsayılan
refBileşeninizin aldığı ref.
Ref<T> | undefined–
DöndürürAçıklama
[0] RefObject<T | null>Öğeye kendi ref'iniz.
[1] (node: T | null) => voidÖğenin ref'ine verin. İki ref'i de doldurur.

Input, Textarea, NativeSelect, Field ve InputGroup.