"UseRef" ve "createRef" arasındaki fark nedir?


104

Karşılaştığım zaman kancaların belgelerine bakıyordum useRef.

Örneğine bakarken…

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>
    </>
  );
}

… İle useRefdeğiştirilebilir gibi görünüyor 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>
    </>
  );
}

Referanslar için neden bir kancaya ihtiyacım var? Neden useRefvar?

Yanıtlar:


132

Aradaki fark, createRefher zaman yeni bir ref yaratacak olmasıdır. Sınıf tabanlı bir bileşende, ref'i genellikle yapım sırasında bir örnek özelliğine koyarsınız (örn. this.input = createRef()). Bir fonksiyon bileşeninde bu seçeneğe sahip değilsiniz. useRefher seferinde ilk görüntülemede olduğu gibi aynı referansı döndürmeye özen gösterir.

İşte bu iki işlevin davranışındaki farkı gösteren örnek bir uygulama:

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);

Düzenle 1rvwnj71x3


34

createRefher zaman, genellikle bir sınıf bileşeninin örneğinde bir alan olarak depoladığınız yeni bir ref döndürür. işlevsel bir bileşenin örneğinin her işlemesinde aynı ref'iuseRef döndürür . Açıkça herhangi bir yerde saklamamanıza rağmen, ref durumunun renderlar arasında kalmasına izin veren şey budur.

İkinci örneğinizde, ref her işlemede yeniden oluşturulur.


Bu yanlış, ifadenizi destekleyecek bir referansınız var mı?
Adeel Imran

Burada React geliştiricilerinden birinin, bunun nasıl çalıştığını açıklayan bir yorumu var: reddit.com/r/reactjs/comments/a2pt15/… Bu cevapla ilgili neyin yanlış olduğunu düşündüğünüzü bilmek isterim.
Joe Clay

Bu soruyu cevaplamaya çalışmadan önce o bağlantıyı görmüştüm, paylaştığınız bağlantıda bu gerçeği nerede ifade ediyor? Bulamadım mı? :)
Adeel Imran

1
Paylaştığım bağlantı useRef, React geliştiricilerinden biri tarafından yayınlanan basitleştirilmiş bir uygulamayı gösteriyor . Bu sadece çağıran aynı değildir createRefgibi createRefbir kanca değildir ve çağrılar arasında herhangi bir devlet kalıcı değil. Ryan Cogswell'in cevabında da farklılıkların güzel bir örneği var.
Joe Clay

1
Bu bağlamdan anladığım kadarıyla, useRef'in createRef'i içinde kullanan özel bir kanca olduğu sonucuna varıldı. Bilgiyi paylaştığınız için teşekkür ederiz.
Adeel Imran

6

tldr

A ref, düz bir JS nesnesidir { current: <some value> }.

React.createRef()referans döndüren bir fabrikadır { current: null }- sihir söz konusu değildir .

useRef(initValue)ayrıca şuna { current: initValue }benzer bir ref döndürür React.createRef(). Ayrıca , bu referansın bir işlev bileşenindeki birden çok işlemede kalıcı olduğunu hatırlar .

React.createRefRef nesnesi bir örnek değişkenine atandığından , dolayısıyla bileşen ve yaşam süresi boyunca erişilebilir olduğundan, sınıf bileşenlerinde kullanmak yeterlidir :
this.myRef = React.createRef(); // stores ref in "mutable" this context (class)

useRef(null)temelde 1'e eşdeğerdir .useState(React.createRef())[0]


1 + useRefile değiştirinuseStatecreateRef

Aşağıdaki tweet benim için aydınlatıcı oldu:

useRef()temelde useState({current: initialValue })[0].

Bölümden elde edilen bilgilerle tldrartık şu sonuca varabiliriz:

useRef(null)temelde useState(React.createRef())[0].

Yukarıdaki kod useState, geri gönderilen referansı sürdürmek için "kötüye kullanır" React.createRef(). [0]sadece değer kısmını seçer useState- [1]ayarlayıcı olacaktır.

useStateaksine bir yeniden oluşturmaya neden olur useRef. Daha resmi olarak React useState, ayarlayıcı yöntemi aracılığıyla yeni bir değer belirlendiğinde eski ve yeni nesne referanslarını karşılaştırır . Biz ise mutasyona durumunu useStatedoğrudan davranışı daha az ya da olur, (ayarlayıcı çağırma karşı) eşdeğer için useRefyeniden işlemek hiçbir artık tetiklenir olarak,:

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

Not: Bunu yapmayın! useRefTekerleği yeniden keşfetmek yerine optimize edilmiş API'yi kullanın. Yukarıda örnekleme amaçlıdır.


3

Sadece bir amacı vurgulamak için:

createRefkadar basit return {current: null}. Bu, ref=pervaneyi en modern şekilde ele almanın bir yolu ve işte bu kadar (dizeye dayalı çok yönlü sihir ve geri arama tabanlı görünüm çok ayrıntılı).

useRefbazı verileri işlemeden önce tutar ve değiştirmek yeniden oluşturmaya neden olmaz (olduğu useStategibi). Nadiren ilişkilidirler. Örnek alanlarına ( this.* =) giden sınıf tabanlı bileşen için beklediğiniz her şey useRef, işlevsel bileşenlerde uygulanacak aday gibi görünür .

Say useCallback, sınırlı sınıf yöntemleri ( this.handleClick = .....bind(this)) olarak çalışır ve yeniden uygulanabilir (ancak tekerleği kesinlikle yeniden icat etmemeliyiz) ile useRef.

Diğer örnekler, DOM referansları, zaman aşımı / aralık kimlikleri, herhangi bir üçüncü taraf kitaplık tanımlayıcıları veya referanslarıdır.

Not: React ekibinin useRefkafa karışıklığını önlemek için farklı adlar seçmesinin daha iyi olduğuna inanıyorum createRef. Belki useAndKeepveya hatta usePermanent.


1

Yine başkalarının cevaplarına başka ama önemli bir katkı.

İçin yeni bir değer ayarlayamazsınız createRef. Ama yapabilirsin 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

ref düz bir nesnedir, currentözelliğini her zamanki gibi değiştirebilirsiniz (sadece test edilmiştir). Başvuru, useRefveya aracılığıyla oluşturulmuşsa önemli değil createRef.
ford04
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.