D3.js w React: Wiązanie danych, SVG oraz zasada własności z useEffect
Dowiedz się, czym naprawdę jest D3, jak działa wiązanie danych do elementów, jak je wprowadzać, aktualizować i usuwać, dlaczego SVG jest do tego odpowiednie, oraz jak podzielić kontrolę nad DOM, aby D3 i React mogły współpracować przy tworzeniu wykresów słupkowych.
Źródła: Harnessing the Power of Data Visualization: Integrating D3.js with React
Trzy rzeczy, które należy wiedzieć najpierw
- D3 to zestaw narzędzi, a nie biblioteka do tworzenia wykresów. Osoby, które spodziewają się czegoś w rodzaju Chart.js, napotykają trudności. D3 to narzędzie niskiego poziomu służące do łączenia danych z elementami DOM, co tłumaczy zarówno jego moc, jak i trudniejszą ścieżkę nauki.
- React i D3 konkurują o te same węzły DOM. Rozwiązanie jest proste: React renderuje kontener SVG, a D3 zarządza wszystkim w jego wnętrzu za pomocą
useEffect. Jeśli pominiesz tę zasadę, spędzisz godziny na rozwiązywaniu dziwnych konfliktów. - Wzorzec enter, update i exit na początku wydaje się dziwny. Po kilku próbach staje się on zrozumiały, a inne podejścia do grafiki opartej na danych wydają się nieudolne.
Czym właściwie jest D3
Nazwa oznacza Dokumenty Zasilane Danymi. Kluczowym słowem jest „dokumenty”: elementy DOM, których wygląd jest określany przez dane. D3 łączy tablice z elementami i umożliwia określenie ich wyglądu na podstawie wartości zawartych w tych tablicach. Wykres to tylko jeden z możliwych wyników, a sama biblioteka nie ma pojęcia o typach wykresów.
Stąd pochodzą zarówno zalety, jak i trudności. D3 nie podejmuje żadnych decyzji za Ciebie. Każda właściwość wizualna, każda oznaka osi, każdy kolor oraz każda interakcja musisz określić sam. Otrzymujesz pełną swobodę twórczą, ale też dużo pracy pisarskiej.
Łączenie danych z DOM
To właśnie tutaj większość początkujących rezygnuje, więc warto to dokładnie przejść krok po kroku.
W zwykłym JavaScript tworzysz element, wypełniasz go treścią i wstawiasz na stronę. Z D3 wybierasz grupę elementów, w tym te, które jeszcze nie istnieją, przypinasz do tej grupy tablicę, a następnie otrzymujesz z powrotem trzy grupy:
- elementy, które już istnieją i potrzebują jedynie nowych danych (grupa do aktualizacji),
- punkty danych, które jeszcze nie mają elementu (grupa do dodania),
- elementy, których dane zniknęły (grupa do usunięcia).
Dziwne jest wywoływanie metod na pustym wyborze. Wybierasz wszystkie elementy rect wewnątrz SVG, które nie zawierają żadnych takich elementów, wywołujesz .data(myArray), potem .enter(), a następnie .append('rect') – i pojawiają się prostokąty. W rzeczywistości .enter() tworzy zastępcę dla każdego danych, który nie ma odpowiadającego mu elementu, a .append() zamienia każdy z tych zastępców w rzeczywisty węzeł. Można to interpretować jako „dla każdego punktu danych bez elementu utwórz jeden”.
Zanim to zadziała, kod D3 wygląda jak magia. Po tym funkcjonuje naturalnie.
Ustawianie właściwości wizualnych na podstawie danych
Gdy dane zostaną powiązane, kolejny krok jest łatwiejszy do zrozumienia. Każdy atrybut lub styl może zostać obliczony na podstawie tych danych:
selection.attr('height', d => yScale(d.value))
Tutaj d to dane przypisane do danego elementu, a yScale to funkcja konwertująca zakres wartości na piksele. Wysokość słupka jest bezpośrednią funkcją jego danych. Zmień dane, uruchom kod ponownie, a wysokość się dostosuje. Prawie wszystko w wizualizacjach D3 sprowadza się do wariantów tej idei: ustawienie właściwości wizualnej jako funkcji wartości granicznej.
Dlaczego SVG?
D3 rysuje na SVG, a powody tego wykraczają poza kwestie historyczne.
SVG opiera się na wektorach, więc kształty są definiowane matematycznie, a nie jako siatki pikseli. Wykres słupkowy, który wygląda wyraźnie na laptopie, będzie równie wyraźny na ekranie 4K bez żadnego dodatkowego wysiłku, a pliki eksportowane nie będą rozmyte przy nieodpowiednich rozdzielczościach.
Dla interaktywności ważne jest to, że kształty SVG to zwykłe elementy DOM i biorą udział w systemie zdarzeń przeglądarki tak samo jak przycisk. Efekt hover, kliknięcie i dotyk działają bez konieczności specjalnych testów zderzeń, ponieważ wystarczy dodać odpowiednie słuchacze.
Koszty stają się widoczne w dużych skali. Tysiące węzłów SVG spowalniają stronę, więc rysowanie 50 000 oddzielnych punktów jako osobnych elementów będzie miało negatywny wpływ. Renderowanie na canvas lepiej radzi sobie w takich sytuacjach. Dla paneli kontrolnych, wykresów biznesowych i większości narzędzi analitycznych SVG jest wystarczający, a integracja z systemem zdarzeń jest tego warta.
Interaktywność i elastyczność
Interfejsy do eksploracji danych, w których użytkownicy dzielą, filtrowają i analizują dane z różnych perspektyw, to obszar, w którym D3 przewyższa statyczne narzędzia do tworzenia wykresów. Można w nich kontrolować każde zdarzenie i przejście.
Większość bibliotek do tworzenia wykresów oferuje gotowe typy wykresów do konfiguracji: słupkowe, liniowe, koliste, z opcjami dotyczącymi kolorów, etykiet i legend. D3 dostarcza natomiast elementy budulcowe: skale, osie, generatorzy ścieżek oraz algorytmy układu. Typ wykresu to po prostu ich kombinacja, więc nie istnieje lista tego, co jest obsługiwane. Jeśli jakiejś wizualizacji nigdzie nie ma, możesz ją stworzyć, a ograniczeniem będą tylko zasady SVG i matematyka.
Cena to dodatkowa praca. To, czy jest to opłacalne, zależy od projektu. Do standardowych wykresów biznesowych wystarczą Recharts lub Chart.js, i można przejść dalej. W przypadku niestandardowych, interaktywnych grafik, gdzie kluczowa jest dokładna prezentacja, D3 jest lepszym wyborem.
Funkcje, których będziesz używać regularnie
To nie jest pełna referencja, tylko te funkcje, które pojawiają się w codziennej pracy:
- d3.select() pobiera pierwszy element pasujący do selektora. W React
d3.select(svgRef.current)to standardowy sposób na uzyskanie dostępu do kontenera. - d3.selectAll() zwraca wszystkie pasujące elementy. Wiązanie danych zazwyczaj zaczyna się tutaj, ponieważ angażuje się kilka elementów.
- selection.data() łączy każdy element z tablicą, dzięki czemu
djest dostępne w późniejszych wywołaniach. Wszystko inne zależy od tego kroku. - selection.enter() tworzy tymczasową selekcję dla danych, które nie mają węzła, a
.append()tworzy następnie te węzły. - selection.attr() ustawia atrybuty, na przykład linię wysokości pokazaną powyżej, co będziecie pisali setki razy.
.attr() lub .style(), a wartości będą się gładko zmieniać, zamieniając nagłe zmiany w animację.d3.max(data, d => d.value).Używanie D3 w React
Problem, o którym nikt nie wspomina, dopóki się z nim nie zderzysz: React utrzymuje wirtualny DOM i wprowadza własne zmiany w tym rzeczywistym, podczas gdy D3 edytuje rzeczywisty DOM bezpośrednio. Jeśli obie biblioteki działają w obrębie jednego elementu, ponowne renderowanie w React nadpisuje prace D3, albo D3 dodaje węzły, o których React nie wie, co powoduje zamieszanie przy następnym renderowaniu.
Skutecznym rozwiązaniem jest podział obowiązków. React renderuje kontener SVG i nie ingeruje w jego zawartość. D3 dostępuje do tego kontenera za pomocą ref i wykonywa wszystkie swoje operacje w funkcji useEffect. Gdy dane się zmieniają, aktualizacja stanu uruchamia tę funkcję, a D3 usuwa stare elementy i rysuje je na nowo. Żadna z bibliotek nie ingeruje w pracę drugiej.
1. Zainstaluj pakiety
Dodaj D3 obok React i ReactDOM za pomocą swojego menedżera pakietów.
npm install d3 react react-dom
Użytkownicy Yarn robią to samo za pomocą własnego polecenia add.
yarn add d3 react react-dom
2. Napisz komponent
Strona React ma jeden zadanie: wyświetlić element SVG i przekazać D3 odniesienie do niego. Nic więcej w wizualizacji nie należy do React.
3. Rysuj w useEffect
Wewnątrz efektu napisz kod D3 tak samo, jak robiłbyś to poza React, używając odniesienia do znalezienia kontenera. Dwie skale zajmują się obliczeniami współrzędnych – jedna mapuje etykiety kategorii na pozycje poziome, a druga mapuje wartości danych na pozycje pionowe. Wysokość każdej kolumnki to dolna krawędź wykresu minus przeskalowana wartość. Ta część sprawia trudności, ponieważ oś y w SVG skierowana jest w dół, więc wyższe kolumnki odpowiadają mniejszym wartościom y.
4. Wyświetl komponent
Umieść komponent w swojej aplikacji i przekaż mu tablicę danych. Zmień tablicę, a wykres zostanie ponownie narysowany: React zauważa zmienioną właściwość, uruchamia efekt, a D3 usuwa stare dane i rysuje nowe. Połączenie między stanem aplikacji a wizualizacją jest automatyczne.
5. Uruchom aplikację
Zainstaluj i uruchom serwer rozwojowy za pomocą npm.
npm start
Lub z Yarn.
yarn start
W przeglądarce zobaczysz wykres słupkowy. Od tego momentu wszystko opiera się na tym samym wzorcu: podpowiedzi przy przewijaniu, skale kolorów, animowane aktualizacje, powiększanie oraz inne typy wykresów. Wszystko to znajduje się w tym efekcie i wykorzystuje funkcje wymienione powyżej.
Podsumowanie
D3 i React współpracują, gdy struktura jest prawidłowa. React odpowiada za kontener i cykl życia komponentu, natomiast D3 za rysowanie w jego wnętrzu. Zachowaj jasną granicę między nimi, aby każda biblioteka pełniła swoją funkcję.
Zaletą jest możliwość tworzenia wizualizacji, których nie oferuje żaden pakiet do wykresów, ponieważ pracujesz z elementami podstawowymi, a nie z opcjami konfiguracji. Gdy sam graf jest częścią wartości produktu, ma to znaczenie. Jeśli panel sterowania potrzebuje jedynie wykresu liniowego, użyj Recharts i uniknij dodatkowych kroków konfiguracji.
Literatura pokrewna
- Harness to Produkt: Praktyczny przewodnik po harnessach w agenticznej sztucznej inteligencji — Dowiedz się, czym jest harness agenta i jakie ma siedem komponentów, od narzędzi i kontekstu po zasady bezpieczeństwa i metody oceny, a także o podagentach, możliwych awariach i frameworkach, które warto znać.
- Inżynieria Harnessu: Środowisko, które sprawia, że agenci sztucznej inteligencji są niezawodne — Co to jest inżynieria harnessu, jakie ma sześć komponentów i trzy filary, jak termin ten pojawił się w 2026 roku oraz dziewięć zasad projektowania dla agentów produkcyjnych.