Apa mereka dan bagaimana menggunakannya

 – Beragampengetahuan
10 mins read

Apa mereka dan bagaimana menggunakannya – Beragampengetahuan

Selama pengembangan, kita biasanya perlu berinteraksi secara langsung dengan elemen DOM. Dalam hal ini, React memberi kita mekanisme yang disebut wasityang memungkinkan akses ke elemen setelah diaktifkan. Paling umum, kami merujuk pada objek standar useRef (Kami menyebutnya), tetapi ada satu lagi yang disebut Wasit Callback. Metode ini memberikan fleksibilitas tambahan dan kontrol atas siklus hidup elemen, memungkinkan kita untuk melakukan tindakan spesifik tertentu pada saat yang tepat ketika kita melampirkan atau memutuskan sambungan dari DOM.

Dalam artikel ini, saya ingin menjelaskan apa panggilan balik itu, dan bagaimana mereka bekerja, mendiskusikan jebakan yang mungkin Anda temui, dan menunjukkan contoh penggunaannya.

Contents

Apa itu panggilan balik dan bagaimana cara kerjanya?

Callback Ref memungkinkan Anda untuk memiliki lebih banyak kontrol granular atas lampiran ref daripada referensi objek. Mari kita lihat bagaimana mereka bekerja dalam praktik:

  1. Memasang. Ketika suatu elemen diinstal ke dalam DOM, React akan memiliki panggilan fungsi REF dengan elemen DOM itu sendiri. Ini memungkinkan Anda untuk melakukan tindakan segera setelah elemen muncul di halaman.
  2. uninstall. Bereaksi panggilan fungsi REF saat elemen diturunkan null. Ini memberi Anda kesempatan untuk membersihkan atau membatalkan tindakan apa pun yang terkait dengan elemen tersebut.

Contoh: instalasi pelacakan dan uninstallasi

import React,  useCallback, useState  from 'react';

function MountUnmountTracker()  null) => 
    if (node) 
      console.log('Element mounted:', node);
     else 
      console.log('Element unmounted');
    
  , []);

  return (
    <div>
      <button onClick=() => setIsVisible((prev) => !prev)>
        isVisible ? 'Hide' : 'Show' element
      </button>
      isVisible && <div ref=handleRef>Tracked element</div>
    </div>
  );


export default MountUnmountTracker;

Setiap kali kami mengganti visibilitas elemen, handleRef Gunakan simpul atau nullmemungkinkan kami untuk melacak saat -saat ketika elemen terhubung atau dipisahkan.

FAQ dan Solusi

Masalah: Ulangi panggilan callback REF

Saat menggunakan callback, masalah umum adalah berulang kali membuat fungsi ref di setiap rerender komponen. Oleh karena itu, React percaya bahwa ini adalah wasit baru, memanggil wasit lama null (Bersihkan) dan kemudian menginisialisasi elemen atau komponen baru tidak benar -benar berubah. Ini dapat menyebabkan efek samping yang tidak perlu.

Contoh masalah

mempertimbangkan Basic Komponen dengan tombol untuk beralih visibilitas div Gunakan referensi panggilan balik, ditambah tombol lain untuk memaksa komponen untuk membuat ulang:

import React,  useState, useReducer  from 'react';

function Basic()  null) => 
    console.log('div', node);
  ;

  return (
    <div>
      <button onClick=toggleDiv>Toggle Div</button>
      <button onClick=forceRerender>Rerender</button>
      showDiv && <div ref=refCallback>Example div</div>
    </div>
  );


export default Basic;

Setiap kali Anda mengklik Rerender Tombol, pelepasan komponen, buat yang baru refCallback Fungsi. Akibatnya, bereaksi panggilan lama refCallback(null) Lalu ada yang baru refCallback(node)bahkan jika elemen yang kita miliki dengan wasit tidak berubah. Di konsol yang akan Anda lihat div null kemudian div [node] Ulangi dan ulangi. Jelas, kami biasanya ingin menghindari panggilan yang tidak perlu seperti ini.

Solusi: Gunakan UseCallback untuk memperingati referensi panggilan balik

Mudah untuk menghindari ini: gunakan saja useCallback Fungsi memori. Dengan cara ini, kecuali jika ketergantungannya berubah, fungsionalitasnya tetap tidak berubah dalam pembawa kembali.

import React,  useState, useCallback, useReducer  from 'react';

function Basic()  null) => 
    console.log('div', node);
  , []);

  return (
    <div>
      <button onClick=toggleDiv>Toggle Div</button>
      <button onClick=forceRerender>Rerender</button>
      showDiv && <div ref=refCallback>Example div</div>
    </div>
  );


export default Basic;

Sekarang, refCallback Dibuat hanya sekali pada render awal. Ini tidak memicu panggilan tambahan dari penjelajahan ulang berikutnya, mencegah panggilan balik yang tidak perlu dan meningkatkan kinerja.

Referensi Callback, Uselayouteffect dan Efek Penggunaan Urutan

Sebelum kita berbicara tentang cara memecahkan masalah tertentu menggunakan referensi callback dalam kode kita, mari kita pahami bagaimana callback referensi dengan useEffect Dan useLayoutEffect Hook sehingga Anda dapat mengatur inisialisasi dan pembersihan sumber daya dengan benar.

Perintah eksekusi

  1. Referensi panggilan balik – Dipanggil segera setelah membuat elemen DOM, maju Efek Hook Run
  2. UselayoutEffect – Jalankan setelah semua mutasi DOM maju Menggambar browser
  3. Efisiensi penggunaan – Jalankan setelah komponen diterjemahkan ke layar
import React,  useEffect, useLayoutEffect, useCallback  from 'react';

function WhenCalled()  null) => 
    if (node) 
      console.log('Callback ref called for div:', node);
     else 
      console.log('Callback ref detached div');
    
  , []);

  useLayoutEffect(() => 
    console.log('useLayoutEffect called');
  , []);

  useEffect(() => 
    console.log('useEffect called');
  , []);

  return (
    <div>
      <div ref=refCallback>Element to watch</div>
    </div>
  );


export default WhenCalled;

Output konsol

  1. Callback ref called for div: [div element]
  2. useLayoutEffect called
  3. useEffect called

Urutan ini memberi tahu kita bahwa Callback Refs dipicu sebelum mengaitkan useLayoutEffect Dan useEffectyang sangat penting untuk mengingat hal ini saat menulis logika.

Masalah apa yang diselesaikan dalam kode?

Pertama, mari kita salin masalah yang biasanya ditemui dengan referensi objek reguler sehingga kita dapat menyelesaikannya dengan callback ref.

import  useCallback, useEffect, useRef, useState  from 'react';

interface ResizeObserverOptions 
  elemRef: React.RefObject<HTMLElement>;
  onResize: ResizeObserverCallback;


function useResizeObserver( elemRef, onResize : ResizeObserverOptions) 
  useEffect(() => 
    const element = elemRef.current;

    if (!element) 
      return;
    

    const resizeObserver = new ResizeObserver(onResize);

    resizeObserver.observe(element);

    return () => 
      resizeObserver.unobserve(element);
    ;
  , [onResize, elemRef]);


export function UsageDom() 
  const [bool, setBool] = useState(false);
  const elemRef = useRef<HTMLDivElement>(null);

  const handleResize = useCallback((entries: ResizeObserverEntry[]) => 
    console.log('resize', entries);
  , []);

  useResizeObserver( elemRef, onResize: handleResize );

  const renderTestText = () => 
    if (bool) 
      return <p ref=elemRef>Test text</p>;
    

    return <div ref=elemRef>Test div</div>;
  ;

  return (
    <div style= width: '100%', textAlign: 'center' >
      <button onClick=() => setBool((v) => !v)>Toggle</button>
      renderTestText()
    </div>
  );

Kami tidak akan masuk ke setiap detail di sini. Singkatnya, kami melacak ukuran kami div atau p Elemen melalui a ResizeObserver. Awalnya, semuanya baik -baik saja: di atas gunung kami bisa mendapatkan ukuran elemen dan kami juga melaporkan ukuran di konsol.

Masalah sebenarnya dimulai ketika kita beralih negara bagian untuk mengganti elemen untuk mengamati. Saat kita mengubah keadaan dan karenanya mengganti elemen yang dilacak, kita ResizeObserver Tidak lagi berfungsi dengan baik. Itu terus mengamati elemen pertama, yang telah dihapus dari DOM! Bahkan beralih kembali ke elemen asli tidak akan membantu, karena langganan ke elemen baru tidak akan pernah terpasang dengan benar.

Catatan: Solusi berikut mewakili lebih banyak apa yang Anda tulis dalam konteks perpustakaan, membutuhkan kode umum. Dalam proyek nyata, Anda dapat menyelesaikannya dengan menggabungkan logo, efek, dan banyak lagi. Tetapi dalam kode perpustakaan, Anda tidak tahu tentang komponen tertentu atau keadaannya. Ini adalah situasi di mana panggilan balik dapat membantu kami.

import  useCallback, useRef, useState  from 'react';

function useResizeObserver(onResize: ResizeObserverCallback) 
  const roRef = useRef<ResizeObserver 

export default function App() 
  const [bool, setBool] = useState(false);

  const handleResize = useCallback((entries: ResizeObserverEntry[]) => 
    console.log('resize', entries);
  , []);

  const resizeRef = useResizeObserver(handleResize);

  const renderTestText = () => 
    if (bool) 
      return <p ref=resizeRef>Test text</p>;
    

    return <div ref=resizeRef>Test div</div>;
  ;

  return (
    <div style= width: '100%', textAlign: 'center' >
      <button onClick=() => setBool((v) => !v)>Toggle</button>
      renderTestText()
    </div>
  );

Seperti yang Anda lihat, kami menulis ulang useResizeObserver Hook menggunakan referensi callback. Kami hanya melewati panggilan balik (yang diingat) yang harus menembak ukuran dan ukuran kami berfungsi dengan baik tidak peduli berapa kali kami beralih. Ini karena pengamat terkait dengan elemen lama pada waktu yang tepat yang kita inginkan dan disediakan oleh panggilan balik.

Manfaat utama di sini adalah bahwa pengembang yang menggunakan kait kami tidak perlu lagi khawatir tentang menambahkan/menghapus logika pengamat di bawah kap – kami telah merangkum logika di dalam kait. Pengembang hanya perlu mengambil panggilan balik ke kait kami dan kemudian memasang wasit yang dikembalikan ke elemennya.

Gabungkan banyak wasit menjadi satu

Ini adalah situasi lain di mana panggilan baliknya adalah untuk menyelamatkan:

import  useEffect, useRef  from 'react';
import  forwardRef, useCallback  from 'react';

interface InputProps 
  value?: string;
  onChange?: React.ChangeEventHandler<HTMLInputElement>;


const Input = forwardRef(function Input(
  props: InputProps,
  ref: React.ForwardedRef<HTMLInputElement>
) 
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => 
    if (!inputRef.current) 
      return;
    

    console.log(inputRef.current.getBoundingClientRect());
  , []);

  return <input ...props ref=ref />;
);

export function UsageWithoutCombine()  null>(null);

  const focus = () => 
    inputRef.current?.focus();
  ;

  return (
    <div>
      <Input ref=inputRef />
      <button onClick=focus>Focus</button>
    </div>
  );

Dalam kode di atas kami memiliki komponen input sederhana di mana kami mengatur ref di atas dan mendapatkannya dari prop forwardRef. Tapi bagaimana kita menggunakannya inputRef intern Input Komponen Bagaimana jika kita juga membutuhkan referensi eksternal untuk fokus atau semacamnya? Mungkin kita ingin melakukan sesuatu yang lain di komponen input itu sendiri, mis. getBoundingClientRect. Mengganti wasit prop dengan wasit internal kami berarti bahwa perhatian eksternal tidak akan lagi berhasil. Jadi, bagaimana kita menggabungkan dua wasit ini?

Di sinilah wasit callback membantu lagi:

import  useEffect, useRef  from 'react';
import  forwardRef, useCallback  from 'react';

type RefItem<T> =
  | ((element: T | null) => void)
  | React.MutableRefObject<T | null>
  | null
  | undefined;

function useCombinedRef<T>(...refs: RefItem<T>[])  null) => 
    refs.forEach((ref) => 
      if (!ref) 
        return;
      

      if (typeof ref === 'function') 
        ref(element);
       else 
        ref.current = element;
      
    );
  , refs);

  return refCb;


interface InputProps 
  value?: string;
  onChange?: React.ChangeEventHandler<HTMLInputElement>;


const Input = forwardRef(function Input(
  props: InputProps,
  ref: React.ForwardedRef<HTMLInputElement>
) 
  const inputRef = useRef<HTMLInputElement>(null);
  const combinedInputRef = useCombinedRef(ref, inputRef);

  useEffect(() => 
    if (!inputRef.current) 
      return;
    

    console.log(inputRef.current.getBoundingClientRect());
  , []);

  return <input ...props ref=combinedInputRef />;
);

export function UsageWithCombine()  null>(null);

  const focus = () => 
    inputRef.current?.focus();
  ;

  return (
    <div>
      <Input ref=inputRef />
      <button onClick=focus>Focus</button>
    </div>
  );

menjelaskan

Kami menerapkan a useCombinedRef Pengembang kait dapat lulus referensi standar, referensi panggilan balik dan opsional null atau undefined. Pengait itu sendiri hanyalah a useCallback Loop itu ada di array wasit. Jika argumennya nullkami mengabaikannya, tetapi jika Ref adalah fungsi, kami menyebutnya elemen. Jika itu wasit standar, kami mengaturnya ref.current ke elemen.

Dengan cara ini, kami menggabungkan beberapa wasit menjadi satu. Dalam contoh di atas, keduanya getBoundingClientRect intern Input Komponen dan panggilan fokus eksternal akan berfungsi dengan baik.

Apa saja perubahan dalam React 19 tentang wasit callback?

Pembersihan Otomatis

Sekarang, ketika elemen dihapus, bereaksi secara otomatis menangani pembersihan referensi callback, membuat manajemen sumber daya lebih mudah. Berikut adalah contoh yang ditunjukkan oleh tim React dalam dokumentasinya:

<input
  ref=(ref) => 
    // ref created

    // NEW: return a cleanup function to reset
    // the ref when element is removed from DOM.
    return () => 
      // ref cleanup
    ;
  
/>

Anda dapat membaca lebih detail tentang hal itu di posting blog resmi, dan akan segera disebutkan null Mungkin sudah usang, meninggalkan metode standar tunggal untuk membersihkan wasit.

Pilih antara wasit normal dan callback referensi

  • Gunakan referensi standar ((useRef) Ketika Anda hanya hanya perlu mengakses elemen DOM atau ingin menjaga nilai -nilai tertentu di antara render tanpa mengambil tindakan lain dalam hal keterikatan atau pemisahan.
  • Gunakan referensi callback Ketika Anda perlu memiliki lebih banyak kontrol granular atas siklus hidup suatu elemen, ketika Anda menulis kode umum (misalnya, di perpustakaan atau paket Anda sendiri) atau perlu mengelola beberapa referensi bersama.

sebagai kesimpulan

Callback Refs in React adalah alat yang kuat yang memberikan pengembang fleksibilitas dan kontrol yang lebih besar saat menggunakan elemen DOM. Dalam kebanyakan kasus, lulus referensi objek standar useRef Ini cukup untuk tugas sehari -hari, tetapi panggilan balik dapat membantu menyelesaikan skenario yang lebih kompleks, seperti yang kita bahas di atas.

rencana pengembangan website



metode pengembangan website

jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website

#Apa #mereka #dan #bagaimana #menggunakannya

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *