Stan, akcja i reducer
Modelowanie funkcji jako czystych reducerów operujących na stanie.
Stan, akcja i reducer to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.
Czym jest Composable Architecture
Composable Architecture, w skrócie TCA, to biblioteka do tworzenia aplikacji Swift o spójnej, testowalnej strukturze. Opiera się na trzech elementach: State, który opisuje dane funkcjonalności, Action, który opisuje każde możliwe zdarzenie, oraz Reducer, który zmienia stan w odpowiedzi na akcje.
Ten jednokierunkowy przepływ sprawia, że funkcjonalności są przewidywalne i łatwe do testowania.
import ComposableArchitecture
// State holds data, Action describes events,
// a Reducer turns (state, action) into the next state.Makro @Reducer
Funkcjonalność definiuje się jako typ oznaczony makrem @Reducer. Makro generuje kod pomocniczy i pozwala zadeklarować State, Action oraz body reduktora razem, w ramach jednej spójnej jednostki.
Zgodnie z konwencją typ nosi nazwę funkcjonalności, na przykład CounterFeature.
import ComposableArchitecture
@Reducer
struct CounterFeature {
// State, Action, and body go here
}Definiowanie State
State jest zwykle strukturą przechowującą wszystkie dane potrzebne funkcjonalności. Oznaczenie go za pomocą @ObservableState pozwala SwiftUI precyzyjnie obserwować zmiany i ponownie renderować tylko to, czego dotyczą.
Stan powinien być minimalny, a wartości pochodne należy obliczać, aby zachować jedno źródło prawdy.
import ComposableArchitecture
@Reducer
struct CounterFeature {
@ObservableState
struct State: Equatable {
var count = 0
}
}Definiowanie Action
Action to enum zawierający każde zdarzenie, które może obsłużyć funkcjonalność: kliknięcia użytkownika, odpowiedzi, tyknięcia timera i tak dalej. Każdy przypadek opisuje coś, co się wydarzyło, a nie polecenie bezpośredniej modyfikacji stanu.
Jasne nazwy akcji sprawiają, że działanie funkcjonalności samo wyjaśnia swoje przeznaczenie.
import ComposableArchitecture
@Reducer
struct CounterFeature {
@ObservableState
struct State: Equatable { var count = 0 }
enum Action {
case incrementTapped
case decrementTapped
}
}Ciało Reducer
Logika reduktora znajduje się w obliczanej właściwości body, która zwraca pewien obiekt typu ReducerOf<Self>. W jej wnętrzu używa się Reduce z domknięciem otrzymującym zmienny state oraz przychodzącą action.
Należy przełączyć się na podstawie akcji i odpowiednio zmodyfikować stan.
import ComposableArchitecture
@Reducer
struct CounterFeature {
@ObservableState
struct State: Equatable { var count = 0 }
enum Action { case incrementTapped, decrementTapped }
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .incrementTapped:
state.count += 1
return .none
case .decrementTapped:
state.count -= 1
return .none
}
}
}
}Zwracanie efektów
Każda gałąź reduktora musi zwracać obiekt typu Effect. Zwrócenie .none oznacza, że po zmianie stanu nie ma już żadnej asynchronicznej pracy do wykonania.
Jeśli potrzebne są efekty uboczne, takie jak wywołanie sieciowe, należy zwrócić efekt wykonujący tę pracę. Efekty zostaną omówione w późniejszej lekcji.
import ComposableArchitecture
// Every reducer branch returns an Effect.
// No side effect needed? Return .none.
// Need async work? Return an effect describing it.
Reduce { state, action in
state.count += 1
return .none
}Mutacje State są scentralizowane
Podstawowa zasada TCA mówi, że tylko reducer modyfikuje stan i robi to wyłącznie w odpowiedzi na akcje. Widoki nigdy nie zmieniają stanu bezpośrednio — wysyłają akcje.
To jedno, centralne miejsce mutacji sprawia, że przepływ danych jest łatwy do śledzenia i testowania.
import ComposableArchitecture
// Views send actions; the reducer mutates state.
// store.send(.incrementTapped) -> state.count += 1
// No direct state mutation outside the reducer.Modelowanie danych wejściowych użytkownika w State
Funkcjonalności oparte na formularzach przechowują edytowalne pola w State i dodają akcje obsługujące ich zmiany. Użycie bindingów dla właściwości pozwala kontrolkom SwiftUI aktualizować je za pośrednictwem akcji w sposób bezpieczny typowo.
W tym przykładzie funkcjonalność śledzi pole tekstowe i przełącznik.
import ComposableArchitecture
@Reducer
struct FormFeature {
@ObservableState
struct State: Equatable {
var name = ""
var isSubscribed = false
}
enum Action: BindableAction {
case binding(BindingAction<State>)
}
var body: some ReducerOf<Self> {
BindingReducer()
}
}Akcje z wartościami powiązanymi
Akcje mogą przenosić dane za pomocą wartości powiązanych. W ten sposób modeluje się zwracane wyniki, takie jak wczytany element lub błąd, aby reducer mógł zapisać je w stanie.
W tym przykładzie akcja odpowiedzi przenosi pobraną liczbę.
import ComposableArchitecture
@Reducer
struct NumberFeature {
@ObservableState
struct State: Equatable { var value = 0 }
enum Action {
case reloadTapped
case responseReceived(Int)
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .reloadTapped:
return .none
case let .responseReceived(value):
state.value = value
return .none
}
}
}
}Dlaczego State zgodny z Equatable pomaga
Zgodność State z Equatable pozwala TCA wykrywać, czy stan rzeczywiście się zmienił, co umożliwia precyzyjne aktualizacje widoków i wyczerpujące testowanie. To niewielkie wymaganie przynosi duże korzyści.
Większość typów stanu może bez dodatkowej pracy przyjąć Equatable, ponieważ ich przechowywane właściwości już go przyjmują.
import ComposableArchitecture
@ObservableState
struct State: Equatable {
var count = 0
var title = ""
}
// Equatable enables change detection and test assertions.Jak wygląda kompletna funkcjonalność
Ukończona funkcjonalność jest czytelna od góry do dołu: najpierw znajduje się makro, następnie obserwowalny stan, enum akcji i ciało reduktora. Cała funkcjonalność mieści się w jednym typie, dzięki czemu elementy TCA można komponować i łatwo przeglądać.
Ten spójny układ powtarza się w każdej funkcjonalności aplikacji.
import ComposableArchitecture
@Reducer
struct CounterFeature {
@ObservableState
struct State: Equatable { var count = 0 }
enum Action { case incrementTapped, decrementTapped }
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .incrementTapped: state.count += 1; return .none
case .decrementTapped: state.count -= 1; return .none
}
}
}
}Szybkie sprawdzenie: trzy elementy
Przypomnij sobie role State, Action i Reducer w TCA.
Podsumowanie: State, Action i Reducer
Poznano najważniejsze elementy funkcjonalności TCA:
@Reducerdefiniuje typ funkcjonalności zawierający wszystko w jednym miejscu.@ObservableStateumieszczone w strukturze przechowuje dane funkcjonalności i umożliwia ich precyzyjną obserwację.- Enum
Actionzawiera każde zdarzenie, opcjonalnie wraz z wartościami powiązanymi. bodyreduktora używaReducedo modyfikowania stanu i zwracaniaEffect, a gdy efekt uboczny nie jest potrzebny, zwraca.none.- Tylko reducer modyfikuje stan, dzięki czemu przepływ danych pozostaje przewidywalny.
Następnie połączysz tę funkcjonalność ze SwiftUI za pomocą Store.
import ComposableArchitecture
// Recap: @Reducer + State + Action + body(Reduce)
// One type, one source of truth, predictable updates.Często zadawane pytania
Czy lekcja „Stan, akcja i reducer” jest bezpłatna?
Tak — pełny tekst „Stan, akcja i reducer” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Stan, akcja i reducer”?
Modelowanie funkcji jako czystych reducerów operujących na stanie. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Swift Academy?
Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Stan, akcja i reducer”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?
Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Stan, akcja i reducer
- Store i integracja z SwiftUI
- Efekty i zależności
- Komponowanie i testowanie funkcji