நவீன ரியாக்ட் மேம்பாட்டில், useImperativeHandle hook என்பது ஒரு கூறுகளின் வெளிப்படும் மதிப்பைத் தனிப்பயனாக்க ஒரு சக்திவாய்ந்த வழியாகும், மேலும் அதன் உள் முறைகள் மற்றும் பண்புகளின் மீது அதிக கட்டுப்பாட்டை அளிக்கிறது. இதன் விளைவாக, மிகவும் திறமையான கூறு APIகள் தயாரிப்பின் நெகிழ்வுத்தன்மை மற்றும் பராமரிப்பை மேம்படுத்தலாம்.
இந்த பகுதியில், சோஷியல் டிஸ்கவரி குரூப் குழுவின் நுண்ணறிவு, ரியாக்ட் கூறுகளை மேம்படுத்துவதற்கு யூஸ்இம்பரேட்டிவ்ஹேண்டில் திறம்பட பயன்படுத்துவதற்கான சிறந்த நடைமுறைகளில் மூழ்கியுள்ளது.
ரியாக்ட் பல கொக்கிகளை வழங்குகிறது (அதிகாரப்பூர்வ ஆவணங்கள் இந்த எழுத்தின்படி 17 கொக்கிகளை விவரிக்கிறது) நிலை, விளைவுகள் மற்றும் கூறுகளுக்கு இடையிலான தொடர்புகளை நிர்வகிப்பதற்கு.
அவற்றில், useImperativeHandle என்பது குழந்தை கூறுகளுக்கான நிரல் இடைமுகத்தை (API) உருவாக்குவதற்கான ஒரு பயனுள்ள கருவியாகும், இது பதிப்பு 16.8.0 இலிருந்து எதிர்வினைக்கு சேர்க்கப்பட்டது.
useImperativeHandle ஆனது ஒரு கூறுக்கு அனுப்பப்பட்ட ref மூலம் என்ன திரும்பப் பெறப்படும் என்பதைத் தனிப்பயனாக்க உங்களை அனுமதிக்கிறது. இது ஃபார்வர்ட்ரெஃப் உடன் இணைந்து செயல்படுகிறது, இது ஒரு குழந்தை கூறுக்கு ஒரு ref ஐ அனுப்ப அனுமதிக்கிறது.
useImperativeHandle(ref, createHandle, [deps]);
இந்த ஹூக் ஒரு கூறுகளின் நடத்தையின் வெளிப்புறக் கட்டுப்பாட்டை அனுமதிக்கிறது, இது மூன்றாம் தரப்பு நூலகங்கள், சிக்கலான அனிமேஷன்கள் அல்லது முறைகளுக்கு நேரடி அணுகல் தேவைப்படும் கூறுகள் போன்ற சில சூழ்நிலைகளில் பயனுள்ளதாக இருக்கும். இருப்பினும், இது ரியாக்டின் அறிவிப்பு அணுகுமுறையை உடைப்பதால், எச்சரிக்கையுடன் பயன்படுத்தப்பட வேண்டும்.
குழந்தை கூறுகளின் DOM ஐ நாம் கையாள வேண்டும் என்று கற்பனை செய்து கொள்வோம். ref ஐப் பயன்படுத்தி இதை எப்படி செய்வது என்பதற்கான எடுத்துக்காட்டு இங்கே.
import React, { forwardRef, useRef } from 'react'; const CustomInput = forwardRef((props, ref) => { // Use forwardRef to pass the ref to the input element return <input ref={ref} {...props} />; }); export default function App() { const inputRef = useRef(); const handleFocus = () => { inputRef.current.focus(); // Directly controlling the input }; const handleClear = () => { inputRef.current.value = ''; // Directly controlling the input value }; return ( <div> <CustomInput ref={inputRef} /> <button onClick={handleFocus}>Focus</button> <button onClick={handleClear}>Clear</button> </div> ); }
UseImperativeHandle ஐப் பயன்படுத்தி அதை எவ்வாறு அடையலாம் என்பது இங்கே.
import React, { useImperativeHandle, forwardRef, useRef } from 'react'; const CustomInput = forwardRef((props, ref) => { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); }, clear: () => { inputRef.current.value = ''; }, })); return <input ref={inputRef} {...props} />; }); export default function App() { const inputRef = useRef(); return ( <div> <CustomInput ref={inputRef} /> <button onClick={inputRef.current.focus}>Focus</button> <button onClick={inputRef.current.clear}>Clear</button> </div> ); }
மேலே உள்ள எடுத்துக்காட்டுகளில் பார்த்தபடி, useImperativeHandle ஐப் பயன்படுத்தும் போது, குழந்தை கூறுகள், நம்மை நாமே வரையறுக்கும் முறைகளின் தொகுப்பை பெற்றோருக்கு வழங்குகிறது.
அனிமேஷனுடனான எடுத்துக்காட்டுகள் போன்ற மேம்பட்ட காட்சிகளில் useImperativeHandle ஐப் பயன்படுத்துவது, ஒரு கூறுக்குள் சிக்கலான நடத்தையை தனிமைப்படுத்த அனுமதிக்கிறது. குறிப்பாக அனிமேஷன் அல்லது ஒலி நூலகங்களுடன் பணிபுரியும் போது இது பெற்றோர் கூறுகளை எளிமையாகவும் படிக்கக்கூடியதாகவும் ஆக்குகிறது.
import React, { useRef, useState, useImperativeHandle, forwardRef, memo } from "react"; import { Player } from '@lottiefiles/react-lottie-player' import animation from "./animation.json"; const AnimationWithSound = memo( forwardRef((props, ref) => { const [isAnimating, setIsAnimating] = useState(false); const animationRef = useRef(null); const targetDivRef = useRef(null); useImperativeHandle( ref, () => ({ startAnimation: () => { setIsAnimating(true); animationRef.current?.play() updateStyles("start"); }, stopAnimation: () => { animationRef.current?.stop() updateStyles("stop"); }, }), [] ); const updateStyles = (action) => { if (typeof window === 'undefined' || !targetDivRef.current) return; if (action === "start") { if (targetDivRef.current.classList.contains(styles.stop)) { targetDivRef.current.classList.remove(styles.stop); } targetDivRef.current.classList.add(styles.start); } else if (action === "stop") { if (targetDivRef.current.classList.contains(styles.start)) { targetDivRef.current.classList.remove(styles.start); } targetDivRef.current.classList.add(styles.stop); } }; return ( <div> <Player src={animation} loop={isAnimating} autoplay={false} style={{width: 200, height: 200}} ref={animationRef} /> <div ref={targetDivRef} className="target-div"> This div changes styles </div> </div> ); }) ); export default function App() { const animationRef = useRef(); const handleStart = () => { animationRef.current.startAnimation(); }; const handleStop = () => { animationRef.current.stopAnimation(); }; return ( <div> <h1>Lottie Animation with Sound</h1> <AnimationWithSound ref={animationRef} /> <button onClick={handleStart}>Start Animation</button> <button onClick={handleStop}>Stop Animation</button> </div> ); }
இந்த எடுத்துக்காட்டில், குழந்தை கூறுகள் ஸ்டார்ட் அனிமேஷன் மற்றும் ஸ்டாப் அனிமேஷன் முறைகளை வழங்குகிறது, இது சிக்கலான தர்க்கத்தை தங்களுக்குள் இணைக்கிறது.
பிழை எப்போதும் உடனடியாக கவனிக்கப்படாது. எடுத்துக்காட்டாக, பெற்றோர் கூறுகள் அடிக்கடி முட்டுகளை மாற்றக்கூடும், மேலும் காலாவதியான முறை (பழைமையான தரவுகளுடன்) தொடர்ந்து பயன்படுத்தப்படும் சூழ்நிலையை நீங்கள் சந்திக்கலாம்.
எடுத்துக்காட்டு பிழை:
https://use-imperative-handle.levkovich.dev/deps-is-not-correct/wrong
const [count, setCount] = useState(0); const increment = useCallback(() => { console.log("Current count in increment:", count); // Shows old value setCount(count + 1); // Are using the old value of count }, [count]); useImperativeHandle( ref, () => ({ increment, // Link to the old function is used }), [] // Array of dependencies do not include increment function );
சரியான அணுகுமுறை:
const [count, setCount] = useState(0); useImperativeHandle( ref, () => ({ increment, }), [increment] // Array of dependencies include increment function );
2. சார்பு வரிசை இல்லை
சார்பு வரிசை வழங்கப்படவில்லை எனில், ImperativeHandle பயன்பாட்டில் உள்ள பொருள் ஒவ்வொரு ரெண்டரிலும் மீண்டும் உருவாக்கப்பட வேண்டும் என்று ரியாக்ட் கருதும். இது குறிப்பிடத்தக்க செயல்திறன் சிக்கல்களை ஏற்படுத்தும், குறிப்பாக கொக்கிக்குள் "கனமான" கணக்கீடுகள் செய்யப்பட்டால்.
எடுத்துக்காட்டு பிழை:
useImperativeHandle(ref, () => { // There is might be a difficult task console.log("useImperativeHandle calculated again"); return { focus: () => {} } }); // Array of dependencies is missing
சரியான அணுகுமுறை:
useImperativeHandle(ref, () => { // There is might be a difficult task console.log("useImperativeHandle calculated again"); return { focus: () => {} } }, []); // Array of dependencies is correct
ref.current இன் நேரடி மாற்றம் எதிர்வினையின் நடத்தையை சீர்குலைக்கிறது. React ஆனது refஐப் புதுப்பிக்க முயற்சித்தால், அது முரண்பாடுகள் அல்லது எதிர்பாராத பிழைகளுக்கு வழிவகுக்கும்.
எடுத்துக்காட்டு பிழை:
useImperativeHandle(ref, () => { // ref is mutated directly ref.current = { customMethod: () => console.log("Error") }; });
சரியான அணுகுமுறை:
useImperativeHandle(ref, () => ({ customMethod: () => console.log("Correct"), }));
useEffect அல்லது Event handlers மூலம் useImperativeHandle மூலம் வழங்கப்படும் அழைப்பு முறைகள், ref ஏற்கனவே உள்ளது எனக் கருதி, பிழைகள் ஏற்படலாம் - அதன் முறைகளை அழைப்பதற்கு முன் எப்போதும் மின்னோட்டத்தைச் சரிபார்க்கவும்.
எடுத்துக்காட்டு பிழை:
const increment = useCallback(() => { childRef.current.increment(); }, [])
சரியான அணுகுமுறை:
const increment = useCallback(() => { if (childRef.current?.increment) { childRef.current.increment() } }, [])
யூஸ்இம்பரேடிவ்ஹேண்டில் ஒரே நேரத்தில் நிலையை மாற்றும் முறைகளை வழங்கினால் (எ.கா., அனிமேஷனைத் தொடங்குதல் மற்றும் ஒரே நேரத்தில் பாணிகளை மாற்றுதல்), அது காட்சி நிலைக்கும் உள் தர்க்கத்திற்கும் இடையே "இடைவெளியை" ஏற்படுத்தலாம். எடுத்துக்காட்டாக, விளைவுகளைப் பயன்படுத்துவதன் மூலம் நிலை மற்றும் காட்சி நடத்தைக்கு இடையே உள்ள நிலைத்தன்மையை உறுதி செய்யவும் (useEffect).
எடுத்துக்காட்டு பிழை:
useImperativeHandle(ref, () => ({ startAnimation: () => { setState("running"); // Animation starts before the state changes lottieRef.current.play(); }, stopAnimation: () => { setState("stopped"); // Animation stops before the state changes lottieRef.current.stop(); }, }));
சரியான அணுகுமுறை:
useEffect(() => { if (state === "running" && lottieRef.current) { lottieRef.current.play(); } else if (state === "stopped" && lottieRef.current) { lottieRef.current.stop(); } }, [state]); // Triggered when the state changes useImperativeHandle( ref, () => ({ startAnimation: () => { setState("running"); }, stopAnimation: () => { setState("stopped"); }, }), [] );
UseImperativeHandle ஐப் பயன்படுத்துவது பின்வரும் சூழ்நிலைகளில் நியாயப்படுத்தப்படுகிறது:
குழந்தை கூறுகளின் நடத்தையைக் கட்டுப்படுத்துதல்: எடுத்துக்காட்டாக, ஒரு சிக்கலான உள்ளீட்டு கூறுக்கு கவனம் செலுத்துதல் அல்லது மீட்டமைக்கும் முறையை வழங்குதல்.
செயல்படுத்தல் விவரங்களை மறைத்தல்: மூலக் கூறு தனக்குத் தேவையான முறைகளை மட்டுமே பெறுகிறது, முழு ref பொருள் அல்ல.
UseImperativeHandle ஐப் பயன்படுத்துவதற்கு முன், இந்த கேள்விகளை நீங்களே கேட்டுக்கொள்ளுங்கள்:
UseImperativeHandle ஹூக்கை மாஸ்டரிங் செய்வதன் மூலம், ரியாக்ட் டெவலப்பர்கள் தேர்ந்தெடுக்கப்பட்ட முறைகளை வெளிப்படுத்துவதன் மூலம் மிகவும் திறமையான மற்றும் பராமரிக்கக்கூடிய கூறுகளை உருவாக்க முடியும். சோஷியல் டிஸ்கவரி குரூப் குழுவால் வகுக்கப்பட்ட நுட்பங்கள் டெவலப்பர்கள் தங்கள் நெகிழ்வுத்தன்மையை மேம்படுத்தவும், அவர்களின் கூறு APIகளை நெறிப்படுத்தவும் மற்றும் ஒட்டுமொத்த பயன்பாட்டின் செயல்திறனை மேம்படுத்தவும் உதவும்.
சமூக கண்டுபிடிப்பு குழுமத்தின் மூத்த மென்பொருள் பொறியாளர் செர்ஜி லெவ்கோவிச் எழுதியது