Гузариш ба мундариҷа
Мавзӯи 7 аз 13
Назария

useRef: унсурҳои DOM ва хотира бе аз нав кашидан

useRef барои чӣ лозим аст

Ҳолат ду хосият дорад: он байни кашиданҳо нигоҳ дошта мешавад ва тағйири он аз нав кашиданро ба вуҷуд меорад. Баъзан танҳо якумаш лозим аст:

  • id-и таймерро дар хотир нигоҳ доштан, то баъд онро қатъ кунем;
  • қимати пешинаи prop-ро дар хотир доштан;
  • истинодро ба унсури DOM нигоҳ доштан, то дар он курсор гузорем, ба он ҳаракат кунем ё андозаашро донем.

Ҳеҷ кадоме аз ин қиматҳо дар экран нишон дода намешавад, пас аз нав кашидан ҳангоми тағйири онҳо лозим нест. Барои ин useRef ҳаст.

Ref чӣ гуна сохта шудааст

const { useRef } = React;

function Example() {
  const clicks = useRef(0);

  function handleClick() {
    clicks.current = clicks.current + 1;
    console.log("Кликҳо: " + clicks.current);
  }

  return <button onClick={handleClick}>Пахш кун</button>;
}
  • useRef(ибтидоӣ) объекти { current: ибтидоӣ }-ро бармегардонад.
  • Ин дар ҳамаи кашиданҳои компонент ҳамон як объект аст — React онро мисли ҳолат нигоҳ медорад.
  • ref.current-ро мустақим хондан ва иваз кардан мумкин аст. React аз ин огоҳ нест ва ҳеҷ чизро аз нав намекашад.

Дар мисол консол 1, 2, 3…-ро нишон медиҳад, вале тугма дар экран ягон бор тағйир намеёбад.

Ref ва ҳолат: фарқ дар чист

useState useRef
Байни кашиданҳо нигоҳ дошта мешавад ҳа ҳа
Тағйир кашиданро ба вуҷуд меорад ҳа не
Чӣ тавр иваз кардан setValue(нав) ref.current = нав
Қимати нав намоён аст дар кашидани навбатӣ фавран
Барои чӣ ҳама чизе, ки дар экран нишон дода мешавад маълумоти хизматӣ ва унсурҳои DOM

Чаро танҳо тағйирёбандаи оддии let timer-ро гирифтан мумкин нест? Чунки функсия-компонент ҳангоми ҳар кашидан аз нав даъват мешавад, ва ҳамаи тағйирёбандаҳои маҳаллии он аз нав сохта мешаванд. Тағйирёбанда бо қимати кашидани пешина гум мешавад. Ref — ин «қуттӣ» аст, ки React онро барои шумо нигоҳ медорад.

Истинод ба унсури DOM

Истифодаи маъмултарин — дастрасӣ ба унсури ҳақиқии саҳифа. Ref-ро ба атрибути ref диҳед, ва баъд аз кашидан React худи гиреҳи DOM-ро ба ref.current мегузорад:

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

  return (
    <div>
      <input ref={inputRef} placeholder="Ҷустуҷӯ" />
      <button onClick={() => inputRef.current.focus()}>Ёфтан</button>
    </div>
  );
}

Бо унсур чӣ кардан мумкин аст:

Вазифа Код
Курсор гузоштан ref.current.focus()
Матнро ҷудо кардан ref.current.select()
Ба унсур ҳаракат кардан ref.current.scrollIntoView({ behavior: "smooth" })
Андозаро донистан ref.current.getBoundingClientRect()
Видеоро оғоз кардан ref.current.play()

Ҳангоми кашидан ref.current барои DOM ҳоло null аст — унсур ҳоло нест. Ба он дар коркардкунандаҳои рӯйдодҳо ва дар эффектҳо муроҷиат кунед:

function AutoFocus() {
  const ref = useRef(null);
  useEffect(() => {
    ref.current.focus();      // унсур аллакай дар саҳифа аст
  }, []);
  return <input ref={ref} />;
}

Ref-ро барои иваз кардани он чи React идора мекунад (матн, синфҳо, унсурҳои дарунӣ) истифода набаред: React ҳангоми кашидани навбатӣ тағйироти шуморо аз нав менависад. Ref барои DOM — ин «баромади эҳтиётӣ» барои он чизест, ки бо JSX ифода кардан мумкин нест: фокус, ҳаракат, андозаҳо, китобхонаҳои берунӣ.

Таймер дар ref

function Timer() {
  const [seconds, setSeconds] = useState(0);
  const intervalRef = useRef(null);

  function start() {
    if (intervalRef.current !== null) return;          // аллакай меравад
    intervalRef.current = setInterval(() => setSeconds((s) => s + 1), 1000);
  }

  function stop() {
    clearInterval(intervalRef.current);
    intervalRef.current = null;
  }

  useEffect(() => stop, []);   // ҳангоми нест кардани компонент — қатъ кардан

  return (
    <div>
      <p>{seconds} с</p>
      <button onClick={start}>Оғоз</button>
      <button onClick={stop}>Ист</button>
    </div>
  );
}

seconds — дар ҳолат: адад дар экран нишон дода мешавад. id-и интервал — дар ref: онро касе намебинад, вале он ба тугмаи «Ист» лозим аст.

Қимати пешина

Ref-е, ки дар эффект нав шудааст, як кашидан «ақиб мемонад» — ҳамин тавр қимати пешинаро дар хотир доштан қулай аст:

function Score({ value }) {
  const prev = useRef(value);
  useEffect(() => {
    prev.current = value;          // баъд аз нишон додан ҷориро дар хотир нигоҳ медорем
  });
  return <p>Буд {prev.current}, шуд {value}</p>;
}

Ҳангоми кашидан prev.current ҳоло қиматро аз дафъаи гузашта нигоҳ медорад, ва баъд аз нишон додан эффект ба он ҷо қимати навро менависад.

Ref ба компоненти худ: forwardRef

Атрибути ref дар тегҳои HTML кор мекунад. Барои додани ref ба компоненти худ ва минбаъд ба унсури дохили он, дар React 18 компонентро ба forwardRef мепечонанд:

const { forwardRef } = React;

const FancyInput = forwardRef(function FancyInput(props, ref) {
  return <input ref={ref} className="fancy" {...props} />;
});

function Form() {
  const ref = useRef(null);
  return (
    <>
      <FancyInput ref={ref} placeholder="Ном" />
      <button onClick={() => ref.current.focus()}>Фокус</button>
    </>
  );
}

(Дар React 19 ref-ро ҳамчун prop-и оддӣ, бе forwardRef қабул кардан мумкин аст.)

Хатоҳои маъмул

  1. Хондани ref.current ҳангоми кашидан барои нишон додан дар экран. Тағйири ref компонентро аз нав намекашад — дар экран қимати кӯҳна мемонад. Ҳама чизе, ки ба корбар намоён аст, — дар ҳолат.
  2. Муроҷиат ба ref-и DOM пеш аз нишон додан. Ҳангоми кашидани аввал дар он null аст. Эффект ё коркардкунандаро истифода баред.
  3. let ба ҷойи ref. Тағйирёбандаи оддӣ ҳангоми ҳар кашидан аз нав сифр мешавад.
  4. Иваз кардани DOM тавассути ref ба ҷойи ҳолат. ref.current.textContent = …-ро React аз нав менависад.

Хулоса

  • useRef(x) → { current: x }, як объект барои тамоми умри компонент.
  • Тағйири ref.current кашиданро ба вуҷуд намеорад. Намоён — дар ҳолат, хизматӣ — дар ref.
  • <input ref={ref} /> — баъд аз нишон додан дар ref.current унсури DOM: focus(), scrollIntoView(), андозаҳо.
  • id-и таймерҳо, қиматҳои пешина, байрақҳои «аллакай бор шуд» — низ дар ref.
  • Барои додани ref ба компоненти худ — forwardRef.

Фокус бо тугма

Осон+10 XP

Компоненти FocusForm-ро нависед: майдони <input> ва тугмаи Edit. Клик ба тугма курсорро ба майдон мегузорад (дар майдон focus()-ро даъват мекунад).

[          ] [Edit]   → клик ба Edit → курсор дар майдон милт-милт мекунад

Барои ҳал кардани масъалаҳо коннекторро пайваст кун

Коди масъалаҳо дар компютери худат иҷро мешавад — ин аз браузер тезтар ва боэътимодтар аст. Барои ин барномаи ройгони коннектори CodeWithMe лозим аст. Онро як бор пайваст кардан кифоя аст.

Коннекторро дар ин компютер ҷустуҷӯ мекунем…

  1. 1
    Коннекторро барои системаи худ (Windows, macOS ё Linux) зеркашӣ кун.Зеркашии коннекторДар саҳифаи зеркашӣ файлеро интихоб кун, ки дар номаш системаи ту ҳаст, масалан windows-amd64.
  2. 2Онро иҷро кун ва ҷузвдонеро интихоб кун, ки ҳалҳоят дар он ҷо меистанд. Python ва Node.js-ро ӯ худаш ҳангоми зарурат ба он ҷо мегузорад.
  3. 3
    Дар поён рамзи 6-рақамаро ворид кун — он дар равзанаи коннектор навишта шудааст («Рамз барои сайти CodeWithMe»). Агар браузер дар бораи дастрасӣ ба шабакаи маҳаллӣ пурсад — иҷозат деҳ.

Коннектор кушода аст (рамзи манбаъ дар GitHub), танҳо дар компютери ту кор мекунад ва кодро танҳо пас аз ворид кардани рамзи пайвастшавӣ иҷро мекунад.