`UseRef` और` createRef` के बीच क्या अंतर है?


120

जब मैं ठोकर खाई तो मैं हुक डॉक्यूमेंटेशन से गुज़र रहा था useRef

उनका उदाहरण देख रहे हैं ...

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

... ऐसा लगता है जैसे इसके useRefसाथ बदला जा सकता है createRef

function TextInputWithFocusButton() {
  const inputRef = createRef(); // what's the diff?
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputRef.current.focus();
  };
  return (
    <>
      <input ref={inputRef} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

मुझे रेफरी के लिए हुक की आवश्यकता क्यों है? क्यों useRefमौजूद है?

जवाबों:


153

अंतर यह है कि createRefहमेशा एक नया रेफरी बनेगा। क्लास-आधारित घटक में, आप आमतौर पर निर्माण (जैसे this.input = createRef()) के दौरान एक उदाहरण संपत्ति में रेफरी डालते हैं । आपके पास फ़ंक्शन घटक में यह विकल्प नहीं है। useRefप्रारंभिक रेंडरिंग के अनुसार प्रत्येक बार समान रेफरी लौटने का ख्याल रखता है।

इन दो कार्यों के व्यवहार में अंतर प्रदर्शित करने वाला एक उदाहरण ऐप यहां दिया गया है:

import React, { useRef, createRef, useState } from "react";
import ReactDOM from "react-dom";

function App() {
  const [renderIndex, setRenderIndex] = useState(1);
  const refFromUseRef = useRef();
  const refFromCreateRef = createRef();
  if (!refFromUseRef.current) {
    refFromUseRef.current = renderIndex;
  }
  if (!refFromCreateRef.current) {
    refFromCreateRef.current = renderIndex;
  }
  return (
    <div className="App">
      Current render index: {renderIndex}
      <br />
      First render index remembered within refFromUseRef.current:
      {refFromUseRef.current}
      <br />
      First render index unsuccessfully remembered within
      refFromCreateRef.current:
      {refFromCreateRef.current}
      <br />
      <button onClick={() => setRenderIndex(prev => prev + 1)}>
        Cause re-render
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

1rwwnj71x3 संपादित करें


38

createRefहमेशा एक नया रेफरी देता है, जिसे आप आम तौर पर एक वर्ग घटक के उदाहरण पर एक क्षेत्र के रूप में संग्रहीत करते हैं। एक कार्यात्मक घटक के उदाहरण के हर रेंडर पर एक ही रेफरीuseRef देता है । यह वही है जो रेफ के राज्य को रेंडरर्स के बीच बने रहने की अनुमति देता है, इसके बावजूद कि आप इसे कहीं भी संग्रहीत नहीं कर रहे हैं।

आपके दूसरे उदाहरण में, रेफ को हर रेंडर पर फिर से बनाया जाएगा।


यह गलत है, क्या आपके पास अपना बयान वापस करने का संदर्भ है?
अदील इमरान

1
यहाँ एक प्रतिक्रिया देने वाले देवों में से एक ने यह समझाते हुए कहा कि यह कैसे काम करता है: reddit.com/r/reactjs/comments/a2pt15/… मुझे यह जानने में दिलचस्पी होगी कि आप इस उत्तर के बारे में क्या सोचते हैं।
जो क्ले

मैंने इस प्रश्न का उत्तर देने से पहले उस लिंक को देखा था, आपके द्वारा साझा किए गए लिंक में यह तथ्य कहां है? मैं यह नहीं मिल सकता है? :)
अदिल इमरान

1
मैंने जो लिंक साझा किया है useRef, वह एक रिएक्ट डेवलपर्स द्वारा पोस्ट किए गए सरलीकृत कार्यान्वयन को दर्शाता है । यह केवल कॉलिंग के समान नहीं है createRef, जैसा createRefकि हुक नहीं है और कॉल के बीच किसी भी स्थिति को जारी नहीं रखता है। रयान कॉगस्वेल के उत्तर में भी मतभेदों का एक अच्छा उदाहरण है।
जो क्ले

1
उस संदर्भ से मेरी समझ केवल अनुमान लगाती है कि useRef एक कस्टम हुक है जो अंदर createRef का उपयोग करता है। ज्ञान बांटने के लिए धन्यवाद।
आदिल इमरान

13

tldr

A refएक सादा JS ऑब्जेक्ट है { current: <some value> }

React.createRef()एक कारखाने में एक रेफरी है { current: null }- कोई जादू शामिल नहीं है

useRef(initValue)भी एक रेफरी के { current: initValue }समान है React.createRef()इसके अलावा , यह memoizes इस रेफरी में कई एक में renders लगातार होने के लिए समारोह घटक

यह React.createRefकक्षा के घटकों में उपयोग करने के लिए पर्याप्त है , क्योंकि रेफ ऑब्जेक्ट को एक उदाहरण चर में सौंपा गया है , इसलिए पूरे घटक और उसके जीवनकाल में पहुंच योग्य है:
this.myRef = React.createRef(); // stores ref in "mutable" this context (class)

useRef(null)मूल रूप से useState(React.createRef())[0] 1 के बराबर है


1 की जगह useRefके साथ useState+createRef

निम्नलिखित ट्वीट मेरे लिए ज्ञानवर्धक रहा है:

useRef()मूल रूप से है useState({current: initialValue })[0]

tldrअनुभाग से अंतर्दृष्टि के साथ , अब हम आगे निष्कर्ष निकाल सकते हैं:

useRef(null)मूल रूप से है useState(React.createRef())[0]

उपरोक्त कोड "एब्यूस" useStateसे लौटे रेफ को बनाए रखने के लिए React.createRef()[0]बस के मान भाग का चयन करता है useState- [1]सेटर होगा।

useStateके विपरीत फिर से प्रस्तुत करने का कारण बनता है useRef। औपचारिक रूप से, प्रतिक्रिया तब पुराने और नए ऑब्जेक्ट संदर्भ की तुलना करती है useState, जब एक नया मान इसके सेटर विधि के माध्यम से सेट किया जाता है। हम तो उत्परिवर्तित के राज्य useStateसीधे (सेटर मंगलाचरण के खिलाफ), अपने व्यवहार और अधिक या कम हो जाता है बराबर करने के लिए useRef, के रूप में कोई फिर से प्रस्तुत करना अब और शुरू हो रहा है:

// Example of mutaing object contained in useState directly
const [ref] = useState({ current: null })
ref.current = 42; // doesn't cause re-render

नोट: ऐसा मत करो! useRefपहिए को सुदृढ़ करने के बजाय अनुकूलित एपीआई का उपयोग करें । ऊपर दृष्टांत प्रयोजनों के लिए है।


3

बस एक उद्देश्य को उजागर करने के लिए:

createRefके रूप में सरल है return {current: null}। यह ref=सबसे आधुनिक तरीके से प्रोप को संभालने का एक तरीका है और यह है (जबकि स्ट्रिंग-आधारित भी एक तरह से जादू है और कॉलबैक-आधारित लुक बहुत वर्बोज़ है)।

useRefरेंडर करने से पहले कुछ डेटा रखता है और इसे बदलने से पुन: रेंडर नहीं होता है (जैसा कि useStateकरता है)। वे शायद ही कभी संबंधित हैं। क्लास-आधारित घटक के लिए आप जो कुछ भी अपेक्षा करते हैं, वह उदाहरण क्षेत्रों में जाता है ( this.* =) useRefकार्यात्मक घटकों के साथ उम्मीदवार के रूप में लागू होता है।

कहते हैं useCallbackकि बंधे हुए वर्ग के तरीके ( this.handleClick = .....bind(this)) के रूप में काम करते हैं और फिर से लागू किए जा सकते हैं (लेकिन हमें पहिया को फिर से आविष्कार नहीं करना चाहिए) useRef

एक अन्य उदाहरण डोम रेफ, टाइमआउट / अंतराल आईडी, किसी भी 3 पार्टी पुस्तकालयों के पहचानकर्ता या संदर्भ हैं।

पीएस मेरा मानना ​​है कि रिएक्ट टीम ने useRefभ्रम से बचने के लिए बेहतर नामकरण चुना createRef। शायद useAndKeepया भी usePermanent


1

फिर भी दूसरे के जवाब के अलावा एक और महत्वपूर्ण है।

आप के लिए एक नया मान सेट नहीं कर सकते createRef। लेकिन आप के लिए कर सकते हैं useRef

const ur = useRef();
const cr = createRef();

ur.current = 10; // you can do it, and value is set
cr.current = 10; // you can, but it's no good, it will not change it

रेफ एक सादे वस्तु है, आप इसकी currentसंपत्ति को हमेशा की तरह बदल सकते हैं (बस परीक्षण किया गया है)। कोई बात नहीं, अगर रेफरी के माध्यम से useRefया बनाया जाता है createRef
ford04
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.