Kodokon kodokon.com

Custom hooks: तर्क को निकालना और फिर से उपयोग करना

stateful तर्क को फिर से उपयोग करने योग्य, composable, testable hooks में निकालें।

8 मिनट · 3 प्रश्न

इस पाठ को Kodokon में खोलें

एक custom hook एक ऐसा फ़ंक्शन है जिसका नाम use से शुरू होता है और जो अन्य hooks कॉल करता है। यह stateful तर्क निकालता है, साझा state नहीं: हर कंपोनेंट जो इसे कॉल करता है उसे अपना ख़ुद का useState और useEffect मिलता है, पूरी तरह अलग-थलग। यह तर्क को अलग निकालने के लिए React का सबसे सीधा उपकरण है - जहाँ HOCs और render props पेड़ में परतें जोड़ते थे, वहाँ एक hook कंपोनेंट के शरीर में समा जाता है, आसानी से compose होता है, और टेस्ट करने में आसान है।

JAVASCRIPT
import { useEffect, useState } from "react";

function useDebouncedValue(value, delay = 300) {
  const [debounced, setDebounced] = useState(value);

  useEffect(() => {
    const id = setTimeout(() => {
      setDebounced(value);
    }, delay);
    return () => clearTimeout(id);
  }, [value, delay]);

  return debounced;
}
cleanup हर बदलाव पर पिछले timer को रद्द कर देता है।

use उपसर्ग सजावटी नहीं है: यही वह चीज़ है जो react-hooks ESLint plugin को आपके फ़ंक्शन के अंदर hooks के नियम जाँचने देती है - बिना शर्त कॉल, शीर्ष स्तर पर। लौटाए गए API के आकार का भी ध्यान रखें: जब उपयोग useState जैसा हो तो एक [value, setValue] tuple, और जैसे ही उजागर करने के लिए दो से अधिक चीज़ें हों तो named keys वाली एक object।

JAVASCRIPT
function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    const stored = localStorage.getItem(key);
    return stored !== null
      ? JSON.parse(stored)
      : initialValue;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
}
आलसी initialization: localStorage केवल mount पर पढ़ा जाता है।

Hooks compose होते हैं: एक hook अन्य hooks कॉल कर सकता है, जिनमें आपके अपने भी शामिल हैं। इसी तरह पठनीय व्यावसायिक abstractions उभरती हैं, जो generic बुनियादी ब्लॉकों पर बनी होती हैं। AbortController का cleanup फ़ंक्शन के साथ मेल पर ध्यान दें: इसके बिना, किसी पुराने input के लिए भेजा गया request सबसे नए के बाद जवाब दे सकता है और उसके परिणाम को अधिलेखित कर सकता है - search fields की क्लासिक race condition

JAVASCRIPT
function useUserSearch(query) {
  const debounced = useDebouncedValue(query, 400);
  const [results, setResults] = useState([]);

  useEffect(() => {
    if (debounced === "") {
      setResults([]);
      return;
    }
    const controller = new AbortController();
    fetch("/api/search?q=" + debounced, {
      signal: controller.signal,
    })
      .then((res) => res.json())
      .then(setResults)
      .catch(() => {});
    return () => controller.abort();
  }, [debounced]);
  return results;
}
व्यावसायिक hook generic hook पर बना है।

ज्ञान जांच

सुनिश्चित करें कि आपको इस पाठ के मुख्य बिंदु याद हैं।

  1. एक custom hook का use उपसर्ग वास्तव में किसके लिए है?
    • यह classes से विरासत में मिली एक विशुद्ध रूप से सजावटी परंपरा है
    • यह linter को फ़ंक्शन को एक hook के रूप में पहचानने और उसके अंदर hooks के नियम जाँचने देता है
    • React इस उपसर्ग के बिना एक stateful फ़ंक्शन चलाने से मना कर देता है
    • यह react से स्वचालित import को ट्रिगर करता है
  2. दो कंपोनेंट एक ही key के साथ useLocalStorage कॉल करते हैं। क्या वे अपनी state साझा करते हैं?
    • हाँ: hook स्वचालित रूप से अपने सभी callers को समकालिक कर देता है
    • नहीं, और डेटा दो अलग-अलग storage keys के अंतर्गत संग्रहीत होता है
    • नहीं: हर कॉल अपनी ख़ुद की React state रखता है; केवल localStorage में मौजूद डेटा साझा होता है
  3. useDebouncedValue में, useEffect द्वारा लौटाए गए cleanup फ़ंक्शन की भूमिका क्या है?
    • लंबित timer को रद्द करना ताकि delay के बाद केवल आख़िरी टाइप किया गया मान प्रकाशित हो
    • हर बार कंपोनेंट unmount होने पर debounced मान को रीसेट करना
    • delay की पूरी अवधि के लिए कंपोनेंट के re-renders को रोकना