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 қабул кардан мумкин аст.)
Хатоҳои маъмул
- Хондани
ref.currentҳангоми кашидан барои нишон додан дар экран. Тағйири ref компонентро аз нав намекашад — дар экран қимати кӯҳна мемонад. Ҳама чизе, ки ба корбар намоён аст, — дар ҳолат. - Муроҷиат ба ref-и DOM пеш аз нишон додан. Ҳангоми кашидани аввал дар он
nullаст. Эффект ё коркардкунандаро истифода баред. letба ҷойи ref. Тағйирёбандаи оддӣ ҳангоми ҳар кашидан аз нав сифр мешавад.- Иваз кардани 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.