Używanie Mobx jako menedżera stanu w natywnych aplikacjach React

Opublikowany: 2022-03-10
Szybkie podsumowanie ↬ MobX jest jednym z wielu narzędzi do zarządzania stanem dostępnych dla programistów React. W tym samouczku Fortune Kay wyjaśnia, czym jest MobX i jak możesz go używać w swoich aplikacjach React, budując je od podstaw.

Zarządzanie stanem jest integralną częścią tworzenia aplikacji JavaScript, zwłaszcza aplikacji React i React Native. W tym samouczku nauczymy się używać biblioteki MobX do zarządzania stanem; zrozumieć podstawowe pojęcia, niektóre przypadki użycia i zbudować prosty przykład.

Uwaga: Podstawowa znajomość Javascript i React Native będzie bardzo przydatna podczas pracy z tym samouczkiem.

Korzystanie z MobX w aplikacjach React

Stan to dane, z którymi pracuje Twój komponent — przechowuje dane, których wymaga komponent i dyktuje, co renderuje komponent. Zarządzanie stanem to proces zarządzania aktualizacją stanu i przekazywaniem go z jednego komponentu do drugiego. Monitorowanie i praca z danymi w aplikacji może być trudna, a to wymaga bibliotek zarządzania stanem. Obsługa wszystkich danych dla Twojej aplikacji może być trochę zniechęcająca, zwłaszcza gdy Twoja aplikacja rośnie w rozmiar i złożoność, budowanie własnego narzędzia do zarządzania stanem jest nie tylko czasochłonne, ale także trudne. Dlatego możesz chcieć użyć biblioteki zarządzania stanem.

Jednak ważne jest, aby wiedzieć, że stan nie jest jedynymi danymi, które renderuje komponent, komponenty mogą również renderować przekazane mu właściwości.

Opcje zarządzania stanem

Biblioteki zarządzania stanem dla aplikacji React Native obejmują; React Context API, Redux, MobX i Unstated Next.

Chociaż każdy z tych menedżerów stanu ma swoje wady i zalety, osobiście polecam MobX ze względu na jego prostotę, minimalny szablonowy kod — nie wymaga on zmiany kodu, ponieważ w swoim rdzeniu MobX jest i wygląda jak JavaScript; nie potrzebujesz zmiany architektury, aby to obsłużyć (w przeciwieństwie do Redux i w mniejszym stopniu Context).

W rzeczywistości jest to tak niewidzialna abstrakcja, że ​​w wielu przypadkach, jeśli usuniesz cały kod MobX — dekoratory @observable , @computed , @action i obserwator , twój kod będzie działał dokładnie tak samo (choć będzie miał pewne problemy z wydajnością ) i nie ogranicza się do państwa globalnego. Oto kilka powodów, dla których warto wybrać MobX jako menedżera stanu z wyboru dla aplikacji React Native.

Chociaż ważne jest również, aby zwrócić uwagę na pewne problemy związane z używaniem MobX jako menedżera stanu, z których niektóre obejmują unikanie zasad jego implementacji, a MobX może być trudny do debugowania, zwłaszcza gdy zmieniasz stan bezpośrednio w komponencie bez użycia @actions parametr.

Co to jest MobX?

Zgodnie z oficjalną dokumentacją, MobX to sprawdzona w boju biblioteka, która sprawia, że ​​zarządzanie stanem jest proste i skalowalne dzięki przejrzystemu zastosowaniu funkcjonalnego programowania reaktywnego. MobX traktuje twoją aplikację jak arkusz kalkulacyjny. Logika jest taka, że ​​wszystko, co można wyprowadzić ze stanu aplikacji, powinno być wykonywane automatycznie .

Architektura stanu MobX
Architektura stanu MobX. (duży podgląd)
Więcej po skoku! Kontynuuj czytanie poniżej ↓

Podstawowe zasady i koncepcja MobX

MobX różni się od innych menedżerów państwowych następującymi koncepcjami.

1. Państwo

Stan to dane, które przechowuje Twoja aplikacja — to mniej więcej cała zawartość jej pamięci. Dotyczy to również twoich komponentów.

2. Pochodne

W MobX wszystko, co można wyprowadzić ze stanu bez interakcji, jest pochodną. Przykłady wyprowadzeń obejmują:

  • Interfejs użytkownika,
  • Dodatki zaplecza, takie jak zmiany na serwerze.

MobX ma dwa główne typy wyprowadzeń:

  • Obliczone wartości
    Wartości wyliczane to w większości wartości, które można wyprowadzić z bieżącego stanu za pomocą czystych funkcji.
  • Reakcje
    Reakcje w pochodnych to efekty uboczne, które występują w wyniku zmian w stanie aplikacji. Są one podobne do wartości obliczonej, ale zamiast wytworzenia nowej wartości, reakcja wywołuje efekt uboczny w postaci takich rzeczy, jak drukowanie na konsoli, wysyłanie żądań sieciowych, przyrostowa aktualizacja drzewa komponentów React w celu załatania DOM i tak dalej.

Złota zasada podczas korzystania z MobX polega na tym, że tworząc wartość na podstawie bieżącego stanu, użyj wartości obliczonej.

3. Działania

W przeciwieństwie do pochodnych akcje to kod, który powoduje zmiany stanu aplikacji — kod, który zmienia stan. Są wszystkim, co modyfikuje państwo. Dzięki MobX możesz to wyraźnie określić w swoim kodzie, akcje to głównie zdarzenia użytkownika, takie jak dane wejściowe, wypychanie danych zaplecza, a nawet zaplanowane zdarzenia.

Aby lepiej zrozumieć akcje, spójrzmy na przykład z dokumentacji MobX.

 class Ticker { @observable tick = 0 @action increment() { this.tick++ // 'this' will always be correct } } const ticker = new Ticker() setInterval(ticker.increment, 1000)

Tutaj ustawiamy @observable z początkową wartością 0. Następnie utworzyliśmy inkrementację funkcji, która jest również akcją, która aktualizuje wartość początkową po wykonaniu tiku co sekundę.

Obserwable w MobX

Elementy obserwowalne lub wartości obserwowalne w MobX to głównie prymitywy JavaScript, zwykłe obiekty, klasy, tablice i mapy. Są one najczęściej używane przez najpierw zadeklarowanie obserwowalnego i dodanie do niego wartości, a następnie wywołanie go przez dodanie @observable, jak pokazano poniżej:

 observable(value) @observable classProperty = value

Podejście do architektury sklepu w MobX

Główna architektura MobX obejmuje części i pomysły, takie jak usługi, sklep, modele przeglądania i kontenery — niektóre z nich wyjaśniono poniżej.

  • Usługa
    Jest to zwykle funkcja wywoływana z kontenera; mogą służyć do pobierania danych z interfejsów API i dodawania do sklepu.
  • Sklep
    Jak sama nazwa wskazuje, jest to centralne miejsce państwa, z którego korzysta aplikacja. Zwykle w MobX obejmują one obserwowalne, zmienne, akcje i obliczone właściwości.
  • Pojemnik
    To wywołuje service i umieszcza dane z View Model do View Component jako @observer decorator ).

MobX w aplikacjach React i natywnych

W celach edukacyjnych w tym samouczku zbudujemy prostą aplikację do tworzenia list, która umożliwi użytkownikowi dodawanie, przeglądanie i usuwanie elementów listy. Będziemy używać MobX jako menedżera stanu w tej aplikacji, aby dodawać listy, aktualizować i usuwać je ze stanu aplikacji. Jednak ważne jest, aby pamiętać, że znasz już podstawowe pojęcia JavaScript i React.

Bez zbędnych ceregieli zacznijmy!

Konfigurowanie środowiska

Teraz, gdy wiemy, czym jest i jak działa MobX, pozwól, że przeprowadzę Cię przez proces konfiguracji Twojego projektu.

Najpierw utwórzmy projekt z następującymi elementami, napisz następujący kod na swoim terminalu, aby zainicjować projekt:

 npx create-react-app listapp

Powyższy kod utworzy samą aplikację React przy użyciu pakietu create-react-app. Przejdź do katalogu projektu:

 cd listapp

Do tej aplikacji będziemy potrzebować trzech komponentów:

  • TitleInput
    Będzie on zawierał tytuł naszego projektu i formularz wejściowy do dodawania list.
  • List
    Będzie to formularz wejściowy, który umożliwi użytkownikowi dodanie listy. Będzie miał przycisk dodawania, aby dodać nasze pozycje na liście.
  • ListsDisplay
    Ten składnik wyświetli wszystkie elementy listy użytkowników, a także przycisk usuwania, który jest generowany automatycznie, gdy użytkownik doda element listy.

Użyjemy Store.js do przechowywania stanu aplikacji i metod jej modyfikacji, podobnie jak w przypadku Redux. Opiszmy, do czego będą używane.

  • mobx
    To jest menedżer stanu, którego będziemy używać w tym projekcie.
  • mobx-react
    To są oficjalne wiązania React dla MobX.
  • bootstrap
    Będziemy używać wersji bootstrap 4.5 do stylizacji naszego projektu.
  • uuid
    Służy do automatycznego tworzenia kluczy do usuwania list.

Zrobiwszy to, zainstalujmy te pakiety. Zamontuję je z alternatywą npm wykonaną w przędzy:

 yarn add mobx mobx-react [email protected] uuid

Po zainstalowaniu pakietów uruchomimy naszą aplikację w trybie deweloperskim, uruchamiając poniższy kod w naszym terminalu:

 yarn start

Konfiguracja naszego sklepu z aplikacjami

Stwórzmy sklep dla naszego projektu. Najpierw utwórz plik w katalogu głównym naszego projektu o nazwie ListStore , będzie to centralna lokalizacja stanu naszej aplikacji.

W przypadku tej aplikacji będziemy musieli utworzyć ListStore , aby nie powtarzać się, gdy używamy go w innych komponentach aplikacji.

 /*** src/Store.js ***/ import { observable, action, computed } from "mobx"; import { v4 } from "uuid"; export class List { @observable value @observable done constructor (value) { this.id = v4() this.value = value } } export class ListStore { @observable lists = [] @observable filter = "" @action addList = (value) => { this.lists.push(new List(value)) } @action deleteList = (list) => { this.lists = this.lists.filter(t => t !== list) } @computed get filteredLists () { const matchCase = new RegExp(this.filter, "i") return this.lists.filter(list=> !this.filter || matchCase.test(list.value)) } }

W powyższym kodzie zaimportowaliśmy trzy funkcje z mobx .

  • observable
    Zawiera zmienną, która może być aktualizowana w przypadku zmiany stanu.
  • action
    Służy do modyfikowania stanu aplikacji.
  • computed
    Wartości, które można wyprowadzić z istniejącego stanu lub innych wartości obliczonych, zmienia się po zmodyfikowaniu stanu.

Klasa List ma dwie wartości obiektów, które są done , oraz value , która będzie przechowywać stan początkowy aplikacji i modyfikację w przypadku zmian.

Chcemy, aby nasza nowa lista automatycznie tworzyła klucz, abyśmy mogli automatycznie uzyskać przycisk usuwania po utworzeniu listy. Tutaj uuid służy do automatycznego tworzenia kluczy w naszej aplikacji.

Następnie dodaliśmy funkcję addList , która doda listy po kliknięciu za pomocą metody .push() w celu wypchnięcia listy do tablicy, którą już utworzyliśmy w tablicy @observable lists .

Funkcja deleteList akceptuje List jako właściwość, która ma być elementem, który użytkownik chce usunąć. Następnie ustawiamy wartość this.Lists na nową tablicę po usunięciu wybranego elementu.

Zarówno addLists , jak i deleteList są akcjami, ponieważ modyfikują stan naszej aplikacji po wprowadzeniu zmian.

Inicjalizacja sklepu MobX

Kolejnym na naszej liście jest zaimportowanie naszego sklepu do naszego App.js i wykorzystanie go w naszym projekcie.

 import React from 'react'; import Navbar from "./components/navbar"; import ListDisplay from "./components/ListDisplay"; import {ListStore} from './ListStore'; function App() { const store = new ListStore() return ( <div> <Navbar store={store}/> <ListDisplay store={store}/> </div> ); } export default App;

Tutaj zaimportowaliśmy komponenty TitleInput i ListDisplay . Następnie zainicjowaliśmy sklep w naszym App.js , aby móc przekazać go jako rekwizyty do komponentów TitleInput i ListDisplay .

Zwykle spowoduje to błąd, ponieważ nie pracowaliśmy nad innymi komponentami, więc zróbmy to. Zbudujmy składnik ListDisplay .

ListDisplay

Ten składnik wyświetla wszystkie dodane przez nas listy, a także automatycznie generuje przycisk usuwania po dodaniu nowej listy.

 import React from 'react' import List from "./List"; import { observer } from 'mobx-react'; function ListDisplay(props) { const { deleteList, filteredLists } = props.store return ( <div> <div className="container"> {filteredLists.map(list => ( <List key={list.id} list={list} deleteList={deleteList} /> ))} </div> </div> ) } export default observer(ListDisplay)

Dla tego komponentu stworzyliśmy funkcję ListDisplay i uczyniliśmy z niej obserwatora, zdestrukturyzowaliśmy również funkcje list i deletelist ze sklepu, robiąc to, ułatwiliśmy wtedy przekazywanie jako rekwizyty obiektów.

Następnie mapujemy filteredLists Listy, aby zwrócić listy, których następnie używamy do budowania indywidualnej listy, przekazując zwrócony element jako właściwości do składnika List .

Po zakończeniu nasz komponent powinien wyglądać tak z dodanymi listami:

Komponent wyświetlania listy
Listy wyświetlane przez komponent `ListDisplay`. (duży podgląd)

Następnie dodaj składniki List i TitleInput .

Komponent listy

Podobnie jak inne nasze komponenty, nasz składnik List wyeksportuje listę jako obserwator, aby pomóc sklepowi obserwować ją pod kątem zmian.

 import React from 'react' import { observer } from 'mobx-react' function List(props) { return ( <div className="card"> <div className="card-body"> <div className="d-flex justify-content-between align-items-center"> <p className={`title ${props.list.done ? "text-secondary" : ""}`}> {props.list.value} </p> <div> <button onClick={props.deleteList.bind(this, props.list)} className="btn btn-danger font-weight-bold py-2 px-5 ml-2"> Delete </button> </div> </div> </div> </div> ) } export default observer(List)

Użyłem bootstrapu do utworzenia kart w pierwszym zestawie divs , a także wyrównałem ikonę usuwania, aby przejść do prawej strony aplikacji. Najpierw utworzyliśmy komponent karty do obsługi naszej list , a następnie stworzyliśmy znacznik przycisku dla button usuwania, który zaakceptuje dwa obiekty tego i przekaże właściwość do listy, która po kliknięciu usunie wybrany element listy z listy na stronie.

Składnik listy
Pojedynczy składnik listy z przyciskiem usuwania. (duży podgląd)

Dalej znajduje się nasz TitleInput , który będzie zawierał nasz formularz wprowadzania do dodawania list i tytuł projektu.

TitleInput

Podobnie jak w innych naszych projektach, dodamy funkcję @observer , aby komponent mógł akceptować rekwizyty z App Store.

 import React, { useState } from 'react' import { observer } from 'mobx-react' function Navbar(props) { const [value, setValue] = useState("") const {addList} = props.store const prepareAddList = (e) => { e.preventDefault() addList(value) setValue("") } return ( <div className="container mt-3"> <h1 className="title">List App</h1> <form onSubmit={prepareAddList} className="form-group"> <div className="row ml-lg-2"> <input className="form-control-lg col-12 col-lg-9 col-sm-12 mr-3 border border-secondary" value={value} type="text" onChange={(e) => setValue(e.target.value)} placeholder="Enter list" /> <button className="col-lg-2 col-5 col-sm-5 mt-2 mt-lg-0 mt-sm-2 btn btn-lg btn-success font-weight-bold"> Add to List </button> </div> </form> </div> ) } export default observer(Navbar)

Najpierw zainicjowaliśmy stan początkowy. Korzystając z haków reakcji, dodaliśmy stan początkowy zwany values , który ustawiamy na pusty ciąg. Używamy tego do przechowywania wartości tego, co jest wprowadzone w polu wejściowym. Aby dowiedzieć się więcej o hakach React, możesz zapoznać się z tym artykułem autorstwa Davida Abioduna.

Następnie wywołaliśmy obiekt dodawania list do sklepu addList i przekazaliśmy go jako rekwizyty ze sklepu z aplikacjami.

Następnie stworzyliśmy funkcję preparedAddList do przyjmowania obiektu zdarzenia dla formularzy wejściowych, dodaliśmy również przycisk do ręcznego dodawania list po kliknięciu.

Prawie gotowe, musimy zrestartować nasz serwer projektu, uruchamiając:

 yarn start

A nasz TitleInput powinien wyglądać tak:

Wprowadzanie tytułu
Tytuł i składnik wejściowy. (duży podgląd)

Skończyliśmy już ze wszystkimi komponentami naszej aplikacji, więc zamontujmy je w naszym App.js . W tym celu musimy zaimportować nasze komponenty titleInput i ListDisplay . Musimy również zaimportować nasz sklep z komponentu Sklep.

Aby MobX działał w naszej aplikacji, musimy przekazać sklep MobX jako rekwizyty w naszej aplikacji i poszczególne komponenty, aby otrzymały właściwości i funkcje w sklepie.

 import React from 'react'; import Navbar from "./components/navbar"; import ListDisplay from "./components/ListDisplay"; import {ListStore} from './ListStore'; function App() { const store = new ListStore() return ( <div> <Navbar store={store}/> <ListDisplay store={store}/> </div> ); } export default App;

Po zakończeniu nasza aplikacja powinna wyglądać tak:

Aplikacja z pełną listą
(duży podgląd)

Wniosek

MobX jest świetnym menedżerem stanu, szczególnie dla aplikacji opartych na React, budując naszą aplikację z listą, poznaliśmy podstawowe pojęcia MobX, stan, pochodne i akcje. Działającą wersję tej aplikacji można znaleźć tutaj:

Możesz pójść dalej, używając MobX w następnej kompilowanej aplikacji, która obejmuje zarządzanie stanem. Chciałbym zobaczyć, jakie nowe rzeczy wymyślisz. Możesz przeczytać więcej o MobX i aplikacjach do zarządzania stanem w poniższych odnośnikach.

Zasoby i referencje

  • „React Native z MobX — pierwsze kroki”, Nader Dabit, Medium
  • „Koncepcje i zasady” MobX (oficjalna dokumentacja)
  • „Najlepsze praktyki z React Hooks”, Adeneye David Abiodun, Smashing Magazine