REACT - pytanie dot architektury

0

Czołem,
Jestem w punkcie w którym muszę zadecydować o docelowej architekturze apki. Kwestia pojawiła się w momencie, kiedy - zaznaczam, że nie używam Reduxa ani MobXa, nie z jakichś tam dogmatycznych przyczyn ale po prostu dlatego, że to jeszcze nie ten etap i mam rozwiązać problem bez tych narzędzi - pojawiła się potrzeba lepszej synchronizacji widoku. Nie wdając się w szczegóły widok dostawał informacje które nie były wzajemnie uzgodnione (na przykład numer strony wybiegał poza zakres dostępnych stron,a oba były zmieniane niezależnie od siebie) i nie dawało się tego uzgodnić, uwierzcie na słowo.
Mam zarys dwóch rozwiązań, pytanie które jest bardziej właściwe.

  1. Cała logika - całe stronicowanie, filtrowanie, sortowanie, dodawanie, usuwanie - trafia do jednej instancji jednej klasy. Obiekt taki jest inicjalizowany w momencie pojawienia się danych wejściowych, ale naistotniejsze, że jest inicjalizowany jako** jedna z wartości stanu głównego komponentu.** komunikuje się z otoczeniem przez swoje metody które są wywoływane przez handlery zdarzeń.
  2. Właściwie jak wyżej ale obiekt jest inicjalizowany przez funkcję render i występuje w funkcji render. To mi się zdecydowanie mniej podoba, wymaga więcej przeróbek, ale czytałam, żeby stanem gospodarować jak najoszczędniej.
0

Właściwie jak wyżej ale obiekt jest inicjalizowany przez funkcję render i występuje w funkcji render.

W jaki sposób initializowany? Pamiętaj, że funkcja renderująca nie powinna odpalać skutków ubocznych.

ale naistotniejsze, że jest inicjalizowany jako jedna z wartości stanu głównego komponentu.

Pamiętaj tylko, że stan w React nie powinien być zmieniany na żywca. Chociaż nie wiem, czy to jakiś dogmat, ale w każdym razie zdrowy rozsądek. Jeśli byś miała robić tak:

class Foo { doSomething() { this.foo = 123; } }
this.state = {foo: new Foo};
...
this.state.foo.doSomething();

To coś mi się wydaje, że nie do końca byłoby ok. I że już lepiej byłoby takie dane trzymać albo poza komponentem (Wstrzykiwane przez props) albo w this (skoro i tak sama to zmieniasz, więc komponent się nie przerenderuje sam, więc po co trzymać w state?):

class Foo { doSomething() { this.foo = 123; } }
...
this.foo = new Foo;
...
this.foo.doSomething();

No i oczywiście przydałby się jakiś sposób na to, żeby powiadamiać obiekt, że dane w obiekcie się zmieniły. I na tym etapie ja ostatnio, kiedy chciałem pracować w React po prostu na czystych obiektach JavaScript, najpierw zacząłem dodawać partyzancko forceUpdate za każdym razem kiedy się cokolwiek zmieniło, a potem w końcu dałem za wygraną i podłączyłem pod te obiekty Mobxa (który jest mniej lub bardziej zgodny z czystymi obiektami) i pracuję na Mobx, który pozwala mi pisać na czystych obiektach, po prostu sam uaktualnia komponenty.

0

Inicjalizacja

 results= formatAndRepairRawDataFromGoogleBooks(results);
                const booksObject = BooksNew.Createfrom(results);
                this.setState({booksObject:booksObject}, ()=>{ if (results.length===0){this.handleBooksNotFound()}else{this.handleBooksFound()}});
                

to jest inicjalizacja - właściwie fragment, do tej pory chyba jeszcze zgodnie ze sztuką
A zatem ramach stanu pojawia się wartość o nazwie booksObject. Oczywiście to jest fragment 1 podejścia, nie będę ustawiać stanu w render, tyle już ogarniam.

Natomiast dalej jest już trochę mniej zgodnie. To jest na przykład wywołanie funkcji sortowania, wszystkie inne handlery miałyby podobną postać.

sortHandle (e) {
   this.state.booksObject.SortingInterface(e);
  this.setState({});
 }
  

this.setState({}) spełnia dokładnie rolę ForceUpdate, gdyż samo wywołanie metody this.state.booksObject.SortingInterface(e) nie wywołuje renderowania. Niby zatem zmieniam ten stan na żywca ale jednak nie do końca. BooksObject ma coś na kształt wewnętrznego stanu, którego zmiany nie wywołują re-renderu.
Będzie też miał dokładnie jednego gettera, więc w pewnym sensie będzie nieźle odizolowany.
A propos MobX a - nawet trochę o tym czytałam, ale z niezrozumiałych przyczyn nie chce się toto doinstalować. Tzn, nie potrafię właściwie zinterpretować i zastosować komunikatów o błędach, a trochę nad tym posiedziałam. Ogólnie, cała ta informa jest do ogarnięcia ale hece ze środowiskiem przerastają mnie.

albo w this (skoro i tak sama to zmieniasz, więc komponent się nie przerenderuje sam, więc po co trzymać w state?):> Miałam kiedyś taką koncepcje ale została trochę zjechana. Poza tym taki zapis będzie w gruncie rzeczy czytelniejszy (znaczy mam na myśli czytelność komponentu App.js,, sporo detali przeniesie się do zewnętrznych funkcji. Ale teraz zastanawiam się ponownie, czyli dać jeden this.bookObjects? Można by i tak

0

Natomiast tak, mi zależałoby właśnie na stwierdzeniu, że ta wersja jest bardziej poprawna/mniej niepoprowna niż tamta.
Chyba zatem zagęszcza się do wersji z przypisaniem obiektu do state - z czego dawałam urywki - i wersji z przypisaniem tego obiektu po prostu do this. No i która mniej razi?

0

this.setState({}); - można zamiast tego this.forceUpdate() co nie będzie wcale wiele lepsze poza tym, że lepiej oddaje intencje, bo podejście to samo - po prostu zmieniasz coś ręcznie i siłą aktualizujesz.

Czyli równie dobrze możesz trzymać jako this.booksObject i robić forceUpdate, bo na to samo wyjdzie docelowo - oczywiście forceUpdate to jest aktualizacja siłą, więc jest to partyzantka. Ale z drugiej strony używanie this.state do tego, do czego nie służy to nie dość że partyzantka to jeszcze hipokryzja.

To już lepiej użyć starego jak świat wzorca obserwatora https://pl.wikipedia.org/wiki/Obserwator_(wzorzec_projektowy)
i albo zaimplementować go samemu albo skorzystać z biblioteki, która gdzieś tam pod spodem z niego w ten czy inny sposób korzysta. Np. Mobx, Redux, Rx.js czy inne (w Mobx będzie najłatwiej).

Z drugiej strony można też robić to korzystając z mechanizmów, które dostarcza sam React - choćby setState, ale wtedy powinnaś to zrobić tak, żeby faktycznie trzymać dane w state (jak to się robi, można popatrzeć w dokumentacji czy w tutorialach).

A propos MobX a - nawet trochę o tym czytałam, ale z niezrozumiałych przyczyn nie chce się toto doinstalować.

A jak to instalujesz? U mnie działa XD

const booksObject = BooksNew.Createfrom(results);

Hmm... W jakim języku pisałaś, zanim zaczęłaś pisać w JavaScript?

0
Ale z drugiej strony używanie this.state do tego, do czego nie służy to nie dość że partyzantka to jeszcze hipokryzja.

W zasadzie nie sposób się nie zgodzić. Tyle, że w dokumentacji( jeżeli nie w dokumentacji to na większości forów tematycznych) znajdowałam informację, że ForceUpdate nie powinno się używać. Zakładałam, że skoro nie znalazłem tego na temat this.setState({}) to mniej kole w oczy, nb jest to wzięte ze Stack Overflow.

 W jakim języku pisałaś, zanim zaczęłaś pisać w JavaScript?

W żadnym. Chodzi o wielkość liter? fakt, to nie jest zbyt konsekwentne. Ale na roboczo pisze tak jak mi podejdzie, jak mam pierwszą działającą wersję to zaczynam ją pieścić.

0

bo C#owcy zaczynają od wielkich liter metody. A BooksNew to też nietypowa nazwa (o co chodzi z tym "New"?), więc myślałem, że przychodzisz z innego języka. W JS zwyczajowo się nazwy metod z małych liter zaczynają, ale każde słowo w środku z dużej: czyli createFrom. Warto się tego trzymać, bo jest to już ustalona konwencja (a JS jest językiem, który odróżnia wielkość liter).

ForceUpdate nie powinno się używać. Zakładałam, że skoro nie znalazłem tego na temat this.setState({}) to mniej kole w oczy, nb jest to wzięte ze Stack Overflow.

Jak dla mnie to mniej kole w oczy forceUpdate skoro faktycznie musisz wymusić apdejt, niż użycie this.setState({}), które jest potworkiem.

Z drugiej strony API Reacta jest dziwne i twórcy jakoś tak zrobili, że this.setState({}) mimo, że wygląda dziwnie to daje mimo wszystko więcej kontroli (np. możesz odpalić shouldComponentUpdate, czego nie daje forceUpdate):

https://reactjs.org/docs/react-component.html#forceupdate
Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate().

https://reactjs.org/docs/react-component.html#setstate
setState() will always lead to a re-render unless shouldComponentUpdate() returns false.

0
LukeJL napisał(a):

bo C#owcy zaczynają od wielkich liter metody. A BooksNew to też nietypowa nazwa (o co chodzi z tym "New"?), więc myślałem, że przychodzisz z innego języka. W JS zwyczajowo się nazwy metod z małych liter zaczynają, ale każde słowo w środku z dużej: czyli createFrom. Warto się tego trzymać, bo jest to już ustalona konwencja (a JS jest językiem, który odróżnia wielkość liter).

ForceUpdate nie powinno się używać. Zakładałam, że skoro nie znalazłem tego na temat this.setState({}) to mniej kole w oczy, nb jest to wzięte ze Stack Overflow.

Jak dla mnie to mniej kole w oczy forceUpdate skoro faktycznie musisz wymusić apdejt, niż użycie this.setState({}), które jest potworkiem.

Z drugiej strony API Reacta jest dziwne i twórcy jakoś tak zrobili, że this.setState({}) mimo, że wygląda dziwnie to daje mimo wszystko więcej kontroli (np. możesz odpalić shouldComponentUpdate, czego nie daje forceUpdate):

https://reactjs.org/docs/react-component.html#forceupdate
Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate().

https://reactjs.org/docs/react-component.html#setstate
setState() will always lead to a re-render unless shouldComponentUpdate() returns false.

BooksNew jest stąd, że to nadal wersja robocza, i równolegle jest również Books. W finalnej to wypadnie oczywiście

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