Unidirectional flow implemented using the latest Swift Generics and Swift Concurrency features.

Overview

swift-unidirectional-flow

Unidirectional flow implemented using the latest Swift Generics and Swift Concurrency features.

struct SearchState: Equatable {
    var repos: [Repo] = []
    var isLoading = false
}

enum SearchAction: Equatable {
    case search(query: String)
    case setResults(repos: [Repo])
}

struct SearchReducer: Reducer {
    func reduce(oldState: SearchState, with action: SearchAction) -> SearchState {
        var state = oldState
        
        switch action {
        case .search:
            state.isLoading = true
        case let .setResults(repos):
            state.repos = repos
            state.isLoading = false
        }
        
        return state
    }
}

struct SearchDependencies {
    var search: (String) async throws -> SearchResponse
}

struct SearchMiddleware: Middleware {
    func process(
        state: SearchState,
        with action: SearchAction,
        using dependencies: SearchDependencies
    ) async -> SearchAction? {
        switch action {
        case let .search(query):
            let results = try? await dependencies.search(query)
            return .setResults(repos: results?.items ?? [])
        default:
            return nil
        }
    }
}

typealias SearchStore = Store<SearchState, SearchAction, SearchDependencies>

struct SearchContainerView: View {
    @StateObject private var store = SearchStore(
        initialState: .init(),
        reducer: SearchReducer(),
        dependencies: .production,
        middlewares: [SearchMiddleware()]
    )
    @State private var query = ""
    
    var body: some View {
        List(store.state.repos) { repo in
            VStack(alignment: .leading) {
                Text(repo.name)
                    .font(.headline)
                
                if let description = repo.description {
                    Text(description)
                }
            }
        }
        .redacted(reason: store.state.isLoading ? .placeholder : [])
        .searchable(text: $query)
        .task(id: query) {
            await store.send(.search(query: query))
        }
        .navigationTitle("Github Search")
    }
}

To learn more about Unidirectional Flow in Swift, take a look at my dedicated post.

You might also like...
A Simple exemple of a launching screen made of 100% using SwuiftUI.
A Simple exemple of a launching screen made of 100% using SwuiftUI.

A Simple exemple of a launching screen made of 100% using SwuiftUI. You can modify and use it in your app Compatible from iOS 14 (older not tested ) to iOS 16 (beta tested only )

Dynamic and type-safe framework for building linear and non-linear flows.

FlowKit FlowKit is a dynamic flow framework capable of building a flow, based on conditions and ordered according to a logic of next steps. By using F

RxSwift extentions for Swift optionals and "Occupiable" types

RxOptional RxSwift extentions for Swift optionals and "Occupiable" types. Usage All operators are available on Driver as well unless otherwise marked.

Simple and lightweight Functional Reactive Coding in Swift for the rest of us
Simple and lightweight Functional Reactive Coding in Swift for the rest of us

The simplest ObservableT implementation for Functional Reactive Programming you will ever find. This library does not use the term FRP (Functional R

Lightweight observations and bindings in Swift
Lightweight observations and bindings in Swift

What is Hanson? Hanson is a simple, lightweight library to observe and bind values in Swift. It's been developed to support the MVVM architecture in o

KVO for Swift - Value Observing and Events

Value Observing and Events for Swift Swift lacks the powerful Key Value Observing (KVO) from Objective-C. But thanks to closures, generics and propert

A sample modulated project to show my knowledge about Swift and Software Development process
A sample modulated project to show my knowledge about Swift and Software Development process

A sample modulated project to show my knowledge about Swift and Software Development process

A Swift event bus for UIWebView/WKWebView and JS.
A Swift event bus for UIWebView/WKWebView and JS.

An event bus for sending messages between UIWebView/WKWebView and embedded JS. Made with pure Swift. Features Easy, fast and reliable event bus system

Cocoa framework and Obj-C dynamism bindings for ReactiveSwift.
Cocoa framework and Obj-C dynamism bindings for ReactiveSwift.

Reactive extensions to Cocoa frameworks, built on top of ReactiveSwift. ⚠️ Looking for the Objective-C API? 🎉 Migrating from RAC 4.x? 🚄 Release Road

Comments
  • How about bigger state?

    How about bigger state?

    Nice example of UDF & swiftUI, but:

    • is there any way / suggestions how to keep state in bigger apps? (I saw that state can derive from another but, I'm afraid of later mess)
    • what about navigation state (should it be part of main state) with newest swiftUI NavigationStack?
    • for big lists with images & stuff how does it affects performance and memory footprint?
    • did you have other examples of bigger apps, how did they avoid complex state?

    I`m just courios & afraid to take risks to implement smth new :)

    opened by adriantabirta 1
Owner
Majid Jabrayilov
Swift developer 👨🏻‍💻SwiftUI addicted 🚀Creator of @CardioBotApp for⌚️and📱Writing weekly posts about Swift development 📖
Majid Jabrayilov
🔄 Unidirectional data flow in Swift.

Reactor Reactor is a framework for making more reactive applications inspired by Elm, Redux, and recent work on ReSwift. It's small and simple (just o

Reactor 175 Jul 9, 2022
Unidirectional Data Flow in Swift - Inspired by Redux

ReSwift Supported Swift Versions: Swift 4.2, 5.x For Swift 3.2 or 4.0 Support use Release 5.0.0 or earlier. For Swift 2.2 Support use Release 2.0.0 or

null 7.3k Jan 3, 2023
MVVM + FLUX iOS Instagram client in Swift, eliminates Massive View Controller in unidirectional event/state flow manner

CZInstagram MVVM + FLUX iOS Instagram client in Swift, eliminates Massive View Controller in unidirectional event/state flow manner. Unidirectional Da

Cheng Zhang 56 Nov 1, 2022
A super simple library for state management with unidirectional data flow.

OneWay ?? OneWay is still experimental. As such, expect things to break and change in the coming months. OneWay is a super simple library for state ma

SeungYeop Yeom 41 Dec 20, 2022
Implementation of the repository pattern in Swift, using generics.

Store Simple, powerful and elegant implementation of the repository pattern, using generics. Why? ?? There are a couple of ways to implement the Repos

Narek Mailian 2 Aug 31, 2022
Unidirectional State Management Architecture for Swift - Inspired by Vuex and Flux

Unidirectional State Management Architecture for Swift - Inspired by Vuex and Flux Introduction VueFlux is the architecture to manage state with unidi

Ryo Aoyama 324 Dec 17, 2022
An array class implemented in Swift that can be observed using ReactiveCocoa's Signals

ReactiveArray An array class implemented in Swift that can be observed using ReactiveCocoa's Signals. Installation Carthage Add the following to your

Wolox 53 Jan 29, 2022
Binding - Data binding framework (view model binding on MVVM) written using propertyWrapper and resultBuilder

Binding Data binding framework (view model binding on MVVM) written using @prope

Sugeng Wibowo 4 Mar 23, 2022
Store-App - Store app made for IOS using Swift programming language

Store-App Store app views products, cart, and using login from https://fakestore

Anas Khalil 2 Jan 1, 2022
This is the demo of MVVM-C structure with dependency injection using RxSwift.

MVVMC-Demo Demo defination This is the demo project, I have integrated two APIs for MovieDB APIS (https://www.themoviedb.org/). One for the listing of

Anshul Shah 61 Dec 6, 2022