We want to hear from you!Take our 2020 Community Survey!

Ref'leri Yönlendirme

Ref yönlendirme bir ref‘i üst bileşenlerden alt bileşenlerin birine otomatik olarak aktarma tekniğidir. Bu genellikle uygulamadaki çoğu bileşen için gerekli değildir. Ama bazı bileşen türleri için faydalı olabilir, özellikle yeniden kullanılabilir bileşen kütüphaneleri için. En yaygın senaryolar aşağıda açıklanmaktadır.

Ref’leri DOM bileşenlerine aktarmak

Yerel (native) button öğesini oluşturan FancyButton bileşenini düşünün:

function FancyButton(props) {
  return (
    <button className="FancyButton">
      {props.children}
    </button>
  );
}

React bileşenleri, render edilen çıktıları da dahil olacak bir şekilde uygulama ayrıntılarını gizler. FancyButton bileşenini kullanan diğer bileşenler, alt button DOM elemanı için genellikle gerekmeyen ref elde ederler.. Bu iyi bir şeydir, çünkü bileşenlerin birbirilerinin DOM yapısına fazla bağımlı olmasını önler.

Her ne kadar bu kapsülleme (encapsulation) FeedStory veya Comment gibi uygulama seviyesi bileşenler için arzu edilse de, FancyButton veya MyTextInput gibi yüksek oranda yeniden kullanılabilir “yaprak” bileşenler için sakıncalı olabilir. Bu bileşenler uygulama boyunca normal bir DOM button ve input öğeleri gibi benzer şekilde kullanılma eğilimindedir, odaklama, seçim veya animasyonları yönetmek için DOM düğümlerine erişmek kaçınılmaz olabilir.

Ref yönlendirme, bazı bileşenlerin aldıkları bir ref’i almasını ve daha alt elemene aktarmasını sağlayan bir etkinleştirme özelliğidir

Alttaki örnekte, FancyButton kendisine aktarılan ref’i elde etmek için React.forwardRef kullanılır ve ardından oluşturduğu DOM button‘a iletir:

const FancyButton = React.forwardRef((props, ref) => (  <button ref={ref} className="FancyButton">    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

Bu şekilde, FancyButton kullanan bileşenler, temelde bulunan button DOM düğümüne bir ref oluşturabilir ve gerekirse doğrudan bir DOM button kullanmış gibi erişebilir.

Yukarıdaki örnekte neler olduğuna dair adım adım açıklama:

  1. React.createRef‘i çağırarak bir React ref oluşturuyoruz ve ref değişkenine atama yapıyoruz.
  2. JSX özelliği olarak belirterek ref‘i <FancyButton ref={ref}> bileşenine aktarıyoruz.
  3. React, ikinci bir argüman olarak ref‘yi forwardRef içindeki (props, ref) => ... fonksiyonuna iletir.
  4. JSX özelliği olarak belirterek, ref argümanını <button ref={ref}>‘a aktarıyoruz.
  5. Ref eklendiğinde. ref.current, <button> DOM düğmüne işaret edecektir.

Not

İkinci ref argümanı yalnızca React.forwardRef çağrısıyla oluşur. Normal fonksiyon veya sınıf bileşenleri ref argümanı almaz, ayrıca ref prop’larda da mevcut değildir.

Ref yönlendirme yalnızca DOM bileşenleri ile sınırlı değildir. ref’leri sınıf bileşenlerinden türetilen nesnelere de aktarabilirsiniz.

Bileşen kütüphanesine bakım yapanlara not

forwardRef‘i bir bileşen içinde kullanmaya başladığınızda, Bunu tehlikeli bir değişim olarak değerlendirmelisiniz ve yeni bir sürüm yayınlamalısınız. Bunun nedeni, kütüphanenizin büyük olasılıkla gözle görülür şekilde farklı bir yaklaşıma sahip olmasıdır (ref’lerin ataması ve hangi türlerin dışa aktarıldığı gibi), ve eski yaklaşıma bağlı uygulamaları ve diğer kütüphaneleri etkiliyebilir.

Mevcut olduğunda React.forwardRef‘i koşullu olarak uygulamak da aynı nedenlerle önerilmez: Kütüphanenizin biçimini değiştirir ve React’i yükselttiklerinde kullanıcılarınızın uygulamalarını bozabilir.

Üst-Seviye Bileşenlerde ref’leri yönlendirme

Bu teknik, üst-seviye bileşenlerde özellikle yararlı olabilir higher-order components (HOC olarak da bilinir). Konsola bileşen prop’larını yazdıran örnek bir HOC ile başlayalım:

function logProps(WrappedComponent) {  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      return <WrappedComponent {...this.props} />;    }
  }

  return LogProps;
}

“logProps” HOC, tüm prop’ları kapladığı bileşene aktarır, böylece sonuç aynı olacaktır. Örneğin, “fancy button” bileşenimize iletilen tüm prop’ları yazdırmak için bu HOC’u kullanabiliriz.

class FancyButton extends React.Component {
  focus() {
    // ...
  }

  // ...
}

// Rather than exporting FancyButton, we export LogProps.
// It will render a FancyButton though.
export default logProps(FancyButton);

Yukarıdaki örnekle ilgili bir uyarı: ref’ler iletilmeyecek. Bunun nedeni ref prop değildir. key gibi, React tarafından farklı şekilde ele alınır. Bir HOC’a ref eklerseniz ref, kaplanmış bileşene değil, en dıştaki kapsaycı bileşene atıfta bulunacaktır.

Bu, FancyButton bileşeni için istenilen ref’lerin aslında LogProps bileşenine ekleneceği anlamına gelir.

import FancyButton from './FancyButton';

const ref = React.createRef();
// The FancyButton component we imported is the LogProps HOC.
// Even though the rendered output will be the same,
// Our ref will point to LogProps instead of the inner FancyButton component!
// This means we can't call e.g. ref.current.focus()
<FancyButton
  label="Click Me"
  handleClick={handleClick}
  ref={ref}/>;

Neyse ki, ref’leri React.forwardRef API’ını kullanarak iç FancyButton bileşenine iletebiliriz. React.forwardRef, props ve ref parametrelerini alan ve bir React düğüm’u döndüren render fonksiyonu kabul eder. Örneğin:

function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      const {forwardedRef, ...rest} = this.props;
      // Assign the custom prop "forwardedRef" as a ref
      return <Component ref={forwardedRef} {...rest} />;    }
  }

  // Note the second param "ref" provided by React.forwardRef.
  // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"
  // And it can then be attached to the Component.
  return React.forwardRef((props, ref) => {    return <LogProps {...props} forwardedRef={ref} />;  });}

Displaying a custom name in DevTools

React.forwardRef render fonksiyonu kabul eder. React DevTools, ref yönlendirme bileşeni için neyin görüntüleneceğini belirlemek için bu fonksiyonu kullanır.

Örneğin, aşağıdaki bileşen DevTools’ta ”ForwardRef” olarak görünür

const WrappedComponent = React.forwardRef((props, ref) => {
  return <LogProps {...props} forwardedRef={ref} />;
});

Oluşturma fonksiyonunu adlandırırsanız, DevTools ayrıca adını da ekler (örn. ”ForwardRef(myFunction)”):

const WrappedComponent = React.forwardRef(
  function myFunction(props, ref) {
    return <LogProps {...props} forwardedRef={ref} />;
  }
);

Hatta fonksiyonun displayName özelliğini kapladığınız bileşeni içerecek şekilde ayarlayabilirsiniz:

function logProps(Component) {
  class LogProps extends React.Component {
    // ...
  }

  function forwardRef(props, ref) {
    return <LogProps {...props} forwardedRef={ref} />;
  }

  // Give this component a more helpful display name in DevTools.
  // e.g. "ForwardRef(logProps(MyComponent))"
  const name = Component.displayName || Component.name;  forwardRef.displayName = `logProps(${name})`;
  return React.forwardRef(forwardRef);
}

Is this page useful?Bu sayfayı düzenle