useRef — DOM ga murojaat, focus, scroll

~15 daq · React · Hooks — Asosiy

Muammo: ba'zan DOM element kerak

React da odatda DOM ga to'g'ridan-to'g'ri tegmaysiz — state va props orqali boshqarasiz. Lekin ba'zi ishlar uchun haqiqiy DOM element kerak bo'ladi:

  • Input ga focus berish
  • Video ni play/pause qilish
  • Elementning o'lchamini o'lchash
  • Scroll pozitsiyasini boshqarish

Bularni state bilan qilib bo'lmaydi. useRef — DOM elementga to'g'ridan-to'g'ri murojaat qilish uchun.


useRef qanday ishlaydi?

import { useRef } from 'react';

function Forma() {
  const inputRef = useRef(null);

  function focusQilish() {
    inputRef.current.focus(); // DOM elementga murojaat
  }

  return (
    <div>
      <input ref={inputRef} placeholder="Ism kiriting" />
      <button onClick={focusQilish}>Focusga ol</button>
    </div>
  );
}
useRef(null) → { current: null }
                        │
JSX render bo'lganda    │
                        ▼
              { current: <input> }  ← haqiqiy DOM element

ref={inputRef} — React bu elementni inputRef.current ga saqlaydi. Komponent chizilgandan keyin inputRef.current — haqiqiy <input> DOM elementi.


Amaliy misollar

Sahifa ochilganda input ga focus

function QidiruvSahifasi() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus(); // sahifa ochilganda darhol focus
  }, []);

  return <input ref={inputRef} placeholder="Qidirish..." />;
}

Video boshqarish

function VideoPlayer() {
  const videoRef = useRef(null);
  const [ishlayapti, setIshlayapti] = useState(false);

  function togglePlay() {
    if (ishlayapti) {
      videoRef.current.pause();
    } else {
      videoRef.current.play();
    }
    setIshlayapti(!ishlayapti);
  }

  return (
    <div>
      <video ref={videoRef} src="/video.mp4" />
      <button onClick={togglePlay}>
        {ishlayapti ? 'Pauza' : 'Play'}
      </button>
    </div>
  );
}

Xabar yuborilganda pastga scroll

function Chat() {
  const [xabarlar, setXabarlar] = useState([]);
  const pastRef = useRef(null);

  useEffect(() => {
    // yangi xabar kelganda pastga scroll
    pastRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [xabarlar]);

  return (
    <div className="chat">
      {xabarlar.map((x, i) => <p key={i}>{x}</p>)}
      <div ref={pastRef} /> {/* eng pastdagi element */}
    </div>
  );
}

Tez-tez uchraydigan xatolar

ref.current ni render vaqtida ishlatish:

function Komponent() {
  const ref = useRef(null);

  // ❌ Xato — render vaqtida DOM hali tayyor emas
  console.log(ref.current.offsetWidth);

  // ✅ To'g'ri — useEffect ichida, DOM tayyor bo'lgandan keyin
  useEffect(() => {
    console.log(ref.current.offsetWidth);
  }, []);

  return <div ref={ref}>...</div>;
}

Shartli render bilan ref:

function Komponent({ korsatilsinmi }) {
  const ref = useRef(null);

  useEffect(() => {
    // ❌ korsatilsinmi=false bo'lsa ref.current = null
    ref.current.focus(); // xato!

    // ✅ Avval tekshiring
    ref.current?.focus();
  }, []);

  return korsatilsinmi ? <input ref={ref} /> : null;
}

Xulosa

const ref = useRef(null);
              │
              └── { current: null }
                           │
                    JSX render keyin
                           │
                           ▼
                  { current: <DOMElement> }

useRef — DOM elementga to'g'ridan-to'g'ri murojaat. Focus, scroll, media boshqarish uchun.

  • ref={...} JSX elementga beriladi
  • ref.current — haqiqiy DOM element
  • Faqat useEffect ichida yoki event handler da ishlating
  • ?. optional chaining — element yo'q bo'lishi mumkin bo'lsa

Keyingi dars

14-dars: useRef — re-render bo'lmasdan qiymat saqlash, useState farqi