Pytanie, czy naprawdę masz potrzebę manipulacji DOMem, czy po prostu nie rozumiesz założeń Reacta.
W React manipuluje się DOMem głównie wtedy, kiedy osadzasz zewnętrzny widżet, która nie korzysta z Reacta. Ew. jeśli z jakichś powodów (bardzo specyficznych!) musisz mieć dostęp do DOMu, żeby porobić specyficzne dla aplikacji haki.
Ogólnie jednak w React manipulację DOMem należy traktować jak tylną furtkę, a nie jak coś normalnego. Zakładając normalną pracę i standardowe problemy, to:
już kompletnie gubie się jeśli muszę zrobić jakaś zaawansowaną manipulacje DOM-em
myślę, że nie do końca myślisz jeszcze w sposób reactowy. Co to znaczy musisz zrobić manipulację DOMem? Prawdopodobnie tylko wydaje ci się, że musisz (poza sytuacjami powyżej).
(np. zbierz wszystkie elementy o klasie "aktywny" następnie pobierz ich pierwszy child po czym wypisz to w modalu).
Myślę, że problemem jest to, że myślisz w kategoriach elementów DOM jako o czymś stałym (same założenia Reacta są takie, żeby o tym nie myśleć, tylko myśleć w kategorii komponentów, które mają jakieś dane na wejściu (propsy, stan, kontekst) i zwracają na tej podstawie informacje, jak powinien wyglądać dany komponent, jakie ma mieć elementy w środku (An element is like a single frame in a movie: it represents the UI at a certain point in time.
oraz In our experience, thinking about how the UI should look at any given moment, rather than how to change it over time, eliminates a whole class of bugs.
https://reactjs.org/docs/rendering-elements.html)
Czyli - próbujesz robić tak jak w jQuery i zakładasz, że elementy DOM są zamontowane na stałe i masz tam wielką piaskownicę i że możesz trzymać sobie stan aplikacji w elementach DOM. A React (podobnie jak cała reszta podobnych bibliotek) mówi "stop. Oddzielmy stan aplikacji od jej wyglądu".
próbujesz zrobić coś takiego (w pseudokodzie)
html = <ul>
<li>Warszawa</li>
<li>Kraków</li>
</ul>
.......
$("ul li").first().html("Wrocław")
a powinieneś zrobić tak (również w pseudokodzie)
cities = ["Warszawa", "Kraków"]
html = <ul>
map each city in cities: <li>{{ city }}</li>
</ul>
........
cities[0] = "Wrocław"
Czyli - trzymać dane/stan aplikacji osobno (czy to w stanie React, czy używając Redux, Mobx czy innej biblioteki, to już rybka), a komponenty traktować jako coś, co ma jakieś wejście(propsy, stan itp.) i na podstawie tego wypluwa to, jak komponent ma wyglądać na wyjściu (czyli paradygmat deklaratywny zamiast imperatywnego)
Jeśli chcesz zmienić coś w aplikacji, to nie tykasz DOMu, tylko idziesz wyżej, do źródła twoich danych (np. stan w React, store w Redux itp. w zależności od tego, jak trzymasz dane) i wykonujesz działanie, które zmieni to źródło danych. Jak zmienisz źródło danych, to się automatycznie zmienią komponenty (pod warunkiem, że będą wiedzieć o tych zmianach, ale to już jest kwestia techniczna zależna od tego, w jaki sposób trzymasz dane i jak się do nich subskrybujesz). Np. prosty komponent funkcyjny:
function Foo() {
const [counter, setCounter] = useState(0);
return <button onClick={() => setCounter(x => x + 1)}>{ counter }</button>
}
zamiast manipulacji DOMem masz setCounter
, który sprawia, że komponent się przerenderuje, a zmienna counter
będzie już większa o 1.
Może być też tak, że twój problem wiąże się ze skalą. Łatwo jest zrobić to na jednym komponencie, ale jak zrobić to na wielu zagnieżdżonych? Bo myślę, że twój problem może wypływać po części z chęci manipulowania wieloma komponentami na raz:
No ale znowu, społeczność Reacta też ma na to rady np.
(np. zbierz wszystkie elementy o klasie "aktywny" następnie pobierz ich pierwszy child po czym wypisz to w modalu).
Raczej powinieneś mieć gdzieś tablicę (trzymaną np. w stanie reactowym) taką:
[
{id: 1, name: "Warszawa", active: true},
{id: 2, name: "Kraków", active: false},
{id: 3, name: "Wrocław", active: false},
]
i operować na takiej liście
- możesz wyrenderować całą tablicę (mapując każdy element tablicy do jakiegoś elementu w JSX), tutaj
id
się przydaje do przekazania właściwości key
czy ogólnie identyfikowania elementów.
- jeśli chcesz pobrać pierwszy element robisz to pobierając pierwszy element tablicy i to przekazać do komponentu renderującego modal
- jeśli chcesz zmienić
active
to zamiast zmieniać coś w DOM, to zmieniasz element w tej tablicy (czy raczej tworzysz nową tablicę z elementem, który jest zmienioną kopią, żeby było wszystko immutable
. Nie powinno się zmieniać stanu Reacta "na pałę")