Porównanie haków do pobierania danych w React

Haki React to potężny sposób zarządzania efektami ubocznymi w komponentach React. Trzy najpopularniejsze hooki do obsługi efektów ubocznych to useEffect, useLayoutEffect i useEffectEvent. Każdy hak ma swoje unikalne zastosowanie, dlatego wybór odpowiedniego do danego zadania jest kluczowy.

Hak useEffect

Hak useEffect to podstawowy hak w React, który umożliwia wykonywanie efektów ubocznych, takich jak manipulacja DOM, operacje asynchroniczne i pobieranie danych w komponentach funkcjonalnych. Ten hak jest funkcją pobierającą dwa argumenty, funkcję efektu i tablicę zależności.

Funkcja efektu zawiera kod wykonujący efekt uboczny, a tablica zależności określa, kiedy funkcja efektu jest uruchamiana. Jeśli tablica zależności jest pusta, funkcja efektu działa tylko raz podczas początkowego renderowania komponentu. W przeciwnym razie funkcja efektu będzie działać za każdym razem, gdy zmieni się którakolwiek wartość w tablicy zależności.

Oto przykład użycia haka useEffect do pobrania danych:

 import React from "react";

function App() {
  const [data, setData] = React.useState([]);

  React.useEffect(() => {
    fetch("<https://jsonplaceholder.typicode.com/posts>")
      .then((response) => response.json())
      .then((data) => setData(data));
  }, []);

  return (
    <div className="app">
      {data.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </div>
  );
}

export default App;

Ten kod demonstruje komponent aplikacji, który pobiera dane z zewnętrznego interfejsu API za pomocą haka useEffect. Funkcja efektu useEffect pobiera przykładowe dane z interfejsu API JSONPlaceholder. Następnie analizuje odpowiedź JSON i ustawia pobrane dane na stan danych.

Dzięki stanowi danych komponent aplikacji renderuje właściwość tytułu każdego elementu w stanie.

Charakterystyka zastosowaniaEffect Hook

  • Przyjazny asynchronicznie: natywnie obsługuje operacje asynchroniczne, dzięki czemu jest wygodne w pobieraniu danych.
  • Działa po renderowaniu: Hak useEffect wykonuje swoje efekty po wyrenderowaniu komponentu przez aplikację, upewniając się, że hak nie blokuje interfejsu użytkownika.
  • Oczyszczanie: zapewnia zintegrowany sposób czyszczenia poprzez zwrócenie funkcji. Może to być szczególnie przydatne podczas pracy ze słuchaczami lub subskrypcjami.

Hak useLayoutEffect

Hak useLayoutEffect jest podobny do haka useEffect, ale działa synchronicznie po wszystkich mutacjach DOM. Oznacza to, że działa, zanim przeglądarka będzie mogła pomalować ekran, dzięki czemu nadaje się do zadań wymagających precyzyjnej kontroli nad układem i stylami DOM, takich jak mierzenie rozmiaru elementu, zmiana rozmiaru elementu lub animowanie jego położenia.

Poniżej znajduje się przykład użycia haka useLayoutEffect do zmiany szerokości elementu przycisku:

 import React from "react";

function App() {
  const button = React.useRef();

  React.useLayoutEffect(() => {
    const { width } = button.current.getBoundingClientRect();

    button.current.style.width = `${width + 12}px`;
  }, []);

  return (
    <div className="app">
      <button ref={button}>Click Me</button>
    </div>
  );
}

export default App;

Powyższy blok kodu zwiększa szerokość elementu przycisku o 12 pikseli przy użyciu haka useLayoutEffect. Dzięki temu szerokość przycisku zwiększy się, zanim zostanie on wyświetlony na ekranie.

Charakterystyka haka useLayoutEffect

  • Synchroniczny: wykonuje się synchronicznie, potencjalnie blokując interfejs użytkownika, jeśli operacja w nim jest skomplikowana.
  • Odczyt/zapis DOM: najlepiej nadaje się do odczytu i zapisu bezpośrednio w DOM, zwłaszcza jeśli potrzebujesz zmian przed ponownym odświeżeniem przeglądarki.

Hak useEffectEvent

Hak useEffectEvent to hak React, który rozwiązuje problemy z zależnościami haka useEffect. Jeśli znasz useEffect, wiesz, że tablica zależności może być trudna. Czasami trzeba umieścić w tablicy zależności więcej wartości, które są absolutnie niezbędne.

Na przykład:

 import React from "react";

function App() {
  const connect = (url) => {
    
  };

  const logConnection = (message, loginOptions) => {
    
  };

  const onConnected = (url, loginOptions) => {
    logConnection(`Connected to ${url}`, loginOptions);
  };

  React.useEffect(() => {
    const device = connect(url);
    device.onConnected(() => {
      onConnected(url);
    });

    return () => {
      device.disconnect();
    };
  }, [url, onConnected]);

  return <div></div>;
}

export default App;

Ten kod demonstruje komponent aplikacji, który zarządza połączeniem z usługą zewnętrzną. Funkcja connect łączy się z określonym adresem URL, natomiast funkcja logConnection rejestruje szczegóły połączenia. Na koniec funkcja onConnected wywołuje funkcję logConnection w celu zarejestrowania komunikatu o pomyślnym połączeniu po nawiązaniu połączenia przez urządzenie.

Hak useEffect wywołuje funkcję connect, a następnie konfiguruje funkcję wywołania zwrotnego onConnected, która będzie wykonywana, gdy urządzenie wyzwoli zdarzenie onConnected. To wywołanie zwrotne rejestruje komunikat połączenia. Zwraca funkcję czyszczącą, która aktywuje się po odmontowaniu komponentu. Ta funkcja czyszczenia odpowiada za odłączenie urządzenia.

Tablica zależności zawiera zmienną url i funkcję onConnected. Komponent App utworzy funkcję onConnected przy każdym renderowaniu. Spowoduje to uruchomienie funkcji useEffect w pętli, która będzie kontynuować ponowne renderowanie komponentu aplikacji.

Istnieje wiele sposobów rozwiązania problemu pętli useEffect. Mimo to najskuteczniejszym sposobem na zrobienie tego bez dodawania kolejnych niepotrzebnych wartości do tablicy zależności jest użycie haka useEffectEvent.

 import React from "react";

function App() {
  const connect = (url) => {
    
  };

  const logConnection = (message, loginOptions) => {
    
  };

  const onConnected = React.useEffectEvent((url, loginOptions) => {
    logConnection(`Connected to ${url}`, loginOptions);
  });

  React.useEffect(() => {
    const device = connect(url);
    device.onConnected(() => {
      onConnected(url);
    });

    return () => {
      device.disconnect();
    };
  }, [url]);

  return <div></div>;
}
export default App;

Owijając funkcję onConnected hakiem useEffectEvent, hak useEffectEvent może zawsze odczytać najnowsze wartości parametrów komunikatu i loginOptions przed przekazaniem ich do haka useEffect. Oznacza to, że useEffect nie musi polegać na funkcji onConnected ani na przekazywanych do niej wartościach.

Hak useEffectEvent jest przydatny, gdy chcesz, aby efekt useEffect był zależny od określonej wartości, nawet jeśli efekt wyzwala zdarzenie wymagające innych wartości, których nie chcesz używać jako zależności w useEffect.

Charakterystyka haka useEffectEvent

  • Najlepiej nadaje się do skutków ubocznych zależnych od zdarzeń.
  • Hak useEffectEvent nie działa z procedurami obsługi zdarzeń, takimi jak onClick, onChange itp.

Hak useEffectEvent jest nadal eksperymentalny i niedostępny w hakach React w wersji 18.

Kiedy używać jakiego haka?

Każdy z powyższych haków do pobierania danych jest odpowiedni w różnych sytuacjach:

  • Pobieranie danych: useEffect to doskonały wybór.
  • Bezpośrednie manipulacje DOM: Jeśli chcesz dokonać synchronicznych zmian w DOM przed odświeżeniem, wybierz useLayoutEffect.
  • Lekkie operacje: W przypadku operacji, które nie powodują ryzyka zablokowania interfejsu użytkownika, możesz swobodnie używać useEffect.
  • Efekty uboczne sterowane zdarzeniami: użyj haka useEffectEvent do zawinięcia zdarzeń i haka useEffect do uruchomienia efektów ubocznych.

Skutecznie radzij sobie ze skutkami ubocznymi

Haki React otwierają świat możliwości, a zrozumienie różnicy między hakami useEffect, useLayoutEffect i useEffectEvent może znacząco wpłynąć na sposób obsługi efektów ubocznych i manipulacji DOM. Aby stworzyć aplikacje przyjazne dla użytkownika, należy wziąć pod uwagę specyficzne wymagania i implikacje tych haków.