Czemu nie powinno zmieniać się bezpośrednio stanu komponentu w React?

0

Czemu nie powinno zmieniać się bezpośrednio stanu komponentu w React? Wtedy komponent ponownie się nie przerenderuje, ale właściwie to czemu?

2
sajek587 napisał(a):

Czemu nie powinno zmieniać się bezpośrednio stanu komponentu w React?

Mówiąc stanu masz na myśli tego z useState()? Jeśłi o to pytasz to można.

Czy masz na myśli to że renderujesz jakiś obiekt obj i zmieniasz mu stan obj.property = "something else";. Bo jeśli tak; to dlatego że stan będzie inny niż to co jest faktycznie wyświetlone w UI (innymi słowy model by się rozjechał z widokiem).

sajek587 napisał(a):

Wtedy komponent ponownie się nie przerenderuje, ale właściwie to czemu?

Dlatego że skąd miałby wiedzieć żę property obiektu się zmieniło. Musiałby dodać odpowiedni listener na to, a właściwie do każdego obiektu który chcielibyśmy wyrenderować. Niektóre biblioteki do UI tak robią, np Vue. Jak sobie wyrenderujesz obiekt, a potem go zinspektujesz to możesz zobaczyć żę są dodane listenery dla set dla każdego atrybutu. React wybrał inną drogę, czyli udostępnienie programiście specjalnego interfejsu którym może dać znać bibliotece że należy przerenderować widok, i jest nim albo ustawienie this.state w komponentach klasowych albo contexty, providery, statey i effekty (również znane jako hooki) w komponentach funkcyjnych.

0

Chyba trochę namieszałem. Chodziło mi o taki update:

this.state.message = 'Hello world'

Ponoć taki zapis nie jest zalecany.

Zalecany zapis jest taki:

this.setState({ message: 'Hello World' })
0
sajek587 napisał(a):

Chyba trochę namieszałem. Chodziło mi o taki update:

this.state.message = 'Hello world'

Ponoć taki zapis nie jest zalecany.

Zalecany zapis jest taki:

this.setState({ message: 'Hello World' })

Nie chodzi o to że jest niezalecany, tylko on po prostu nie zadziała (poza konstruktorem; bo jak ustawisz this.state.message w konstruktorze to będzie git).

Jak zrobisz this.state.message = "Hello, world" (już po utworzeniu i zmontowaniu komponentu, czyli w trakcie działania) to widok się nie odświeży.

Możesz o tym poczytać tutaj: https://reactjs.org/docs/state-and-lifecycle.html

PS: Ale tak serio, to nie używaj klasowych komponetów. Używaj raczej funkcyjnych.

0
sajek587 napisał(a):

Właśnie wiem, że wtedy komponent się nie przerenderuje, ale nie wiem czemu.

W taki sposób został zaprojektowany interejs komponentów w reakcie.

Mogli podjąć decyzję, o dodaniu dodatkowych elementów w bibliotece żeby interfejs dopuszczał takie zmiany, ale nie została taka decyzja podjęta. Chyba że pytasz dlaczego właśnie w taki sposób zaprojektowano bibliotekę? Moim zdaniem po to żeby dać większą kontrolę programiście nt cyklu życia komponentu i uprościć bibliotekę i proces renderu. Np udostępniając metody componentWillMount, componentWillRender, componentDidMount, etc. Poza tym, należałoby też rozważyć - jeśli zmiana this.state.message powodowałaby za każym razem rerender, to trzeba by się zastanowić czy jeśli ustawię dwie na raz wartości, np this.state.one = "One"; this.state.two = "two"; to czy mają iść dwa rerendery czy jeden? A jeśłi jeden, to jak to zaimplementować? Potem należałoby sobie odpowiedzieć na pytanie czy np taki call powinien robić rerender this.state.one = this.state.one;. Poza tym, żeby takie coś działało; to musiałbyś albo robić checki po metodach life cycle, żeby sprawdzić czy state sie zmienił; albo musiałbyś dodać listener na property state'ów, oraz na sam obiekt, żeby sprawdzić czy wartość się dodała. Aha, noi skoro this.state.message = "one" miały robić render, to również this.state.a.b.c.d.e.f.g.h.j.j = "one"; musiałby robić rerender żeby zachować spójność, a więc takie dodawanie listenerów należałoby dodać na arbitralnie głębokim poziomie zagnieżdżenia. Noi też ktoś powiedziałby że jeśli można ustawić this.state.message = "one", to mogłoby to też działać dla array'a, np this.state.messages[12] = "new value";.

To nie jest takie proste jak się wydaje, że "powinno się po prostu móc zrobić this.state.message = "one";.

0
TomRiddle napisał(a):
sajek587 napisał(a):

Właśnie wiem, że wtedy komponent się nie przerenderuje, ale nie wiem czemu.

W taki sposób został zaprojektowany interejs komponentów w reakcie.

Mogli podjąć decyzję, o dodaniu dodatkowych elementów w bibliotece żeby interfejs dopuszczał takie zmiany, ale nie została taka decyzja podjęta. Chyba że pytasz dlaczego właśnie w taki sposób zaprojektowano bibliotekę? Moim zdaniem po to żeby dać większą kontrolę programiście nt cyklu życia komponentu i uprościć bibliotekę i proces renderu. Np udostępniając metody componentWillMount, componentWillRender, componentDidMount, etc. Poza tym, należałoby też rozważyć - jeśli zmiana this.state.message powodowałaby za każym razem rerender, to trzeba by się zastanowić czy jeśli ustawię dwie na raz wartości, np this.state.one = "One"; this.state.two = "two"; to czy mają iść dwa rerendery czy jeden? A jeśłi jeden, to jak to zaimplementować? Potem należałoby sobie odpowiedzieć na pytanie czy np taki call powinien robić rerender this.state.one = this.state.one;. Poza tym, żeby takie coś działało; to musiałbyś albo robić checki po metodach life cycle, żeby sprawdzić czy state sie zmienił; albo musiałbyś dodać listener na property state'ów, oraz na sam obiekt, żeby sprawdzić czy wartość się dodała. Aha, noi skoro this.state.message = "one" miały robić render, to również this.state.a.b.c.d.e.f.g.h.j.j = "one"; musiałby robić rerender żeby zachować spójność, a więc takie dodawanie listenerów należałoby dodać na arbitralnie głębokim poziomie zagnieżdżenia. Noi też ktoś powiedziałby że jeśli można ustawić this.state.message = "one", to mogłoby to też działać dla array'a, np this.state.messages[12] = "new value";.

To nie jest takie proste jak się wydaje, że "powinno się po prostu móc zrobić this.state.message = "one";.

Ale to nadal mi nie tłumaczy dlaczego użycie setState renderuje ponownie komponent, a this.state.message = "one" już nie. Po prostu tak jest i już? Czy np. chodzi o to, że setState tworzy nową referencję obiektu stanu i temu ponownie się renderuje?

0
sajek587 napisał(a):

Ale to nadal mi nie tłumaczy dlaczego użycie setState renderuje ponownie komponent, a this.state.message = "one" już nie. Po prostu tak jest i już? Czy np. chodzi o to, że setState tworzy nową referencję obiektu stanu i temu ponownie się renderuje?

Rozumiem że jesteś ciekaw; i taka analiza implementacji czasem może wiele nauczyć, ale nie jestem pewien czy jedna z największych bibliotek do UI to dobry start.

Jeśli jednak nadal chcesz szukać to tu możęsz zacząć: https://github.com/numbbbbb/read-react-source-code/blob/master/03-how-setstate-works-part-1.md

1 użytkowników online, w tym zalogowanych: 0, gości: 1