Skip to content

⚛️ GoodReactor is a Redux-inspired Reactor framework for iOS developed using Swift. It enables seamless communication between the View Model, View Controller, and Coordinator through state and navigation functions. It ensures no side-effects by interacting with dependencies outside of the Reduce function. Integrate it with using SPM!

License

GoodRequest/GoodReactor

Repository files navigation

Logo

GoodReactor

Check out the Documentation

iOS Version Swift Version Supported devices Contains Test Dependency Manager

GoodReactor is an adaptation of the Reactor framework that is Redux inspired. The view model communicates with the view controller via the State and with the Coordinator via the navigation function. You communicate to the viewModel via Actions Viewmodel changes state in the Reduce function Viewmodel interactes with dependencies outside of the Reduce function not to create side-effects

Link to the original reactor kit: https://github.com/ReactorKit/ReactorKit

Installation

Swift Package Manager

Create a Package.swift file and add the package dependency into the dependencies list. Or to integrate without package.swift add it through the Xcode add package interface.

import PackageDescription

let package = Package(
    name: "SampleProject",
    dependencies: [
        .Package(url: "https://github.com/GoodRequest/GoodReactor" from: "addVersion")
    ]
)

Usage

GoodReactor

ViewModel

In your ViewModel define State, Actions and Mutations

  • State defines all data that you work with
  • Action user actions that are sent from the ViewController.
  • Mutation represents state changes.
    struct State {

        var counterValue: Int

    }

    enum Action {

        case updateCounterValue(CounterMode)
        case goToAbout

    }

    enum Mutation {

        case counterValueUpdated(Int)

    }

In the mutate function define what will happen when certain actions are called:

func mutate(action: Action) -> AnyPublisher<Mutation, Never> {
    switch action {
        case .updateCounterValue(let mode):
        return updateCounter(mode: mode)
        }
}
    
func updateCounter(mode: CounterMode) -> AnyPublisher<Mutation,Never> {
    var actualValue = currentState.counterValue

    switch mode {
        case .increase:
        actualValue += 1

        case .decrease:
        actualValue -= 1
    }

    return Just(.counterValueUpdated(actualValue)).eraseToAnyPublisher()
}

Finally in the reduce function define state changes according to certain mutation:

    func reduce(state: State, mutation: Mutation) -> State {
        var state = state

        switch mutation {
        case .counterValueUpdated(let newValue):
            state.counterValue = newValue
        }

        return state
    }

ViewController

From ViewController you can send actions to ViewModel via Combine just like in our GoodReactor-Sample or like this:

viewModel.send(event: yourAction)

Then use combine to subscribe to state changes, so every time the state is changed, ViewController is updated as well:

viewModel.state
    .map { String($0.counterValue) }
    .removeDuplicates()
    .assign(to: \.text, on: counterValueLabel, ownership: .weak)
    .store(in: &cancellables)

GoodCoordinator

When viewModel's action is called, navigation function is called as well. There you can hande the app flow, for example:

func navigate(action: Action) -> AppStep? {
    switch action {
        case .goToAbout:
        return .home(.goToAbout)

        default:
        return .none
    }
}

License

GoodReactor repository is released under the MIT license. See LICENSE for details.

About

⚛️ GoodReactor is a Redux-inspired Reactor framework for iOS developed using Swift. It enables seamless communication between the View Model, View Controller, and Coordinator through state and navigation functions. It ensures no side-effects by interacting with dependencies outside of the Reduce function. Integrate it with using SPM!

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages