useImperativeHandle Hook — կոմպոնենտների վերահսկում ref-ի միջոցով
React-ում սովորաբար տվյալները փոխանցվում են վերևից ներքև՝ props-երի միջոցով։ Սակայն երբեմն անհրաժեշտ է, որ ծնող կոմպոնենտը կարողանա ուղղակիորեն կանչել երեխայի մեթոդներ կամ ֆունկցիաներ։ Օրինակ՝ բացել կամ փակել modal, scroll անել list-ը, կամ reset անել input-ի արժեքը։ Այս դեպքում React-ը տրամադրում է useImperativeHandle hook-ը՝ աշխատելու համար forwardRef-ի հետ։
🔹 Ինչ է useImperativeHandle-ը
useImperativeHandle(ref, createHandle, deps)
հրամայում է React-ին, թե ինչ պետք է տեսնի ծնողը, երբ օգտագործում է ref-ը տվյալ կոմպոնենտի վրա։
- ref — ref-ը, որը փոխանցվում է
forwardRef-ով։ - createHandle — ֆունկցիա, որը վերադարձնում է օբյեկտ՝ այն մեթոդներով և արժեքներով, որոնք ցանկանում ենք հրապարակել։
- deps — dependency array (ըստ ցանկության)՝ վերահսկելու handle-ի թարմացումները։
📍 Օրինակ 1 — Ծնողը կառավարում է երեխայի focus-ը
Ստեղծենք կոմպոնենտ, որը ներսում ունի input և իր սեփական focus մեթոդ։ Ծնող կոմպոնենտը կկարողանա կանչել այդ մեթոդը ref-ի միջոցով։
// CustomInput.js
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const CustomInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
clear: () => {
inputRef.current.value = '';
}
}));
return (
<input
ref={inputRef}
type="text"
placeholder="Գրիր ինչ-որ բան..."
/>
);
});
export default CustomInput;
Օգտագործում ծնողի մեջ
// App.js
import React, { useRef } from 'react';
import CustomInput from './CustomInput';
export default function App() {
const inputRef = useRef();
return (
<div>
<CustomInput ref={inputRef} />
<br />
<button onClick={() => inputRef.current.focus()}>Focus</button>
<button onClick={() => inputRef.current.clear()}>Clear</button>
</div>
);
}
Այստեղ ծնողը (App) կարողանում է կանչել երեխայի (CustomInput) մեթոդները՝
focus() և clear(), առանց props փոխանցելու։
Այսպիսով, մենք ստեղծեցինք փոքր “public API” երեխայի համար։
🧠 Ինչու է պետք useImperativeHandle
Առանց useImperativeHandle, React-ը ref-ի միջոցով ծնողին կտար DOM node-ը (օր. input-ի հղումը)։ Բայց շատ դեպքերում դա բավարար չէ։ useImperativeHandle-ի միջոցով մենք կարող ենք տալ ծնողին միայն այն մեթոդները կամ տվյալները, որոնք ուզում ենք վերահսկել։
Այս մոտեցումը հատկապես օգտակար է՝ երբ ցանկանում ես սահմանափակել ծնողի հասանելիությունը ներքին լոգիկային։
📍 Օրինակ 2 — Modal կոմպոնենտի կառավարում ծնողի կողմից
Սա պրոֆեսիոնալ օրինակ է, որտեղ ծնողը բացում և փակում է modal-ը՝ ref-ի միջոցով։
// Modal.js
import React, { useState, forwardRef, useImperativeHandle } from 'react';
const Modal = forwardRef((props, ref) => {
const [isOpen, setIsOpen] = useState(false);
useImperativeHandle(ref, () => ({
open: () => setIsOpen(true),
close: () => setIsOpen(false)
}));
if (!isOpen) return null;
return (
<div style={{
position: 'fixed',
top: 0, left: 0, right: 0, bottom: 0,
background: 'rgba(0,0,0,0.5)',
display: 'flex', justifyContent: 'center', alignItems: 'center'
}}>
<div style={{ background: 'white', padding: '20px', borderRadius: '8px' }}>
<h3>Modal պատուհան</h3>
<button onClick={() => setIsOpen(false)}>Փակել</button>
</div>
</div>
);
});
export default Modal;
// App.js
import React, { useRef } from 'react';
import Modal from './Modal';
export default function App() {
const modalRef = useRef();
return (
<div>
<button onClick={() => modalRef.current.open()}>Բացել Modal</button>
<Modal ref={modalRef} />
</div>
);
}
Այս օրինակում ծնողը լիովին վերահսկում է երեխայի վարքը՝ առանց props-երի։ Այն շատ նման է imperatively “openModal()” կամ “closeModal()” ֆունկցիաների գործելաոճին։
⚙️ Լավագույն պրակտիկաներ
- Օգտագործիր useImperativeHandle միայն այն ժամանակ, երբ անհրաժեշտ է վերահսկել ներքին լոգիկան ծնողի կողմից։
- Մի փոխանցիր ամբողջ DOM ref ծնողին, սահմանիր միայն անհրաժեշտ մեթոդները։
- Մի օգտագործիր այս hook-ը data flow-ի համար՝ այն նախատեսված չէ state փոխանակման համար։
🧩 Խորքային օրինակ — սահմանափակ հասանելիություն ref-ի միջոցով
Երբեմն ցանկանում ես, որ ծնողը չկարողանա հասնել բոլոր ներքին մեթոդներին։ useImperativeHandle-ը թույլ է տալիս “թաքցնել” մնացածը։
useImperativeHandle(ref, () => ({
open: () => setVisible(true),
close: () => setVisible(false)
}), []); // միայն երկու մեթոդ հասանելի ծնողին
Այս ձևով ծնողը չի կարող փոխել state-ը կամ DOM-ը ուղղակիորեն։
🎯 Վարժություն (փորձիր ինքդ)
Գրիր կոմպոնենտ, որը․
- Ունի input դաշտ։
- Ունի focus() և reset() մեթոդներ՝ սահմանված useImperativeHandle-ով։
- Ծնողը կարող է կանչել այդ մեթոդները ref-ի միջոցով։
📘 Ամփոփում
- useImperativeHandle — React-ի advanced hook է՝ սահմանելու համար երեխայի ref-ի “public API”-ն։
- Աշխատում է միայն forwardRef-ի հետ։
- Օգտակար է modal, tooltip, input և scroll control կոմպոնենտների դեպքում։
- Օգնում է թաքցնել ներքին լոգիկան ծնողի հասանելիությունից։