Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving to Action-Mutation-State model #19

Merged
merged 15 commits into from
Apr 17, 2017
Merged

Moving to Action-Mutation-State model #19

merged 15 commits into from
Apr 17, 2017

Conversation

devxoul
Copy link
Owner

@devxoul devxoul commented Mar 25, 2017

Design Goal

  • Functional & Reactive
  • Testable
  • Explicit
  • Easy to use
  • Less typing (compare to other patterns)

Summary

  • Input becomes Action.
  • Output becomes State.
  • Action and State are self-contained and independent.
  • Use a single input subject and single output observable instead of exposing each properties.
  • Every reactor has:
    • func mutate(State, Action) -> Observable<Mutation>
    • func reduce(State, Mutation) -> State

Example

View (ViewController)

class TaskListViewController: UIViewController, View {
  func bind(reactor: TaskListViewReactor) {
    // Action
    self.rx.viewDidLoad.map(Reactor.Action.refresh)
      .bindTo(reactor.action)
      .addDisposableTo(self.disposeBag)

    self.editButton.rx.tap.map(Reactor.Action.toggleEditing)
      .bindTo(reactor.action)
      .addDisposableTo(self.disposeBag)

    // State
    reactor.state.map { $0.isEditing }
      .bindTo(self.tableView.rx.isEditing)
      .addDisposableTo(self.disposeBag)

    reactor.state.map { $0.tasks }
      .bindTo(self.tableView.rx.items(foo))
      .addDisposableTo(self.disposeBag)
  }
}

Reactor

class TaskListViewReactor: Reactor {
  enum Action {
    case refresh()
    case toggleEditing()
    case addTask(Task)
    case deleteTask(Int)
  }

  typealias Mutation = Action

  struct State {
    var isEditing: Bool
    var tasks: [Task]
  }

  override func reduce(state: State, mutation: Mutation) -> State {
    var state = state
    switch action {
    case .refresh:
      state.tasks = refreshedTaskFromSomewhere
      return state

    case .toggleEditing:
      state.isEditing = !state.isEditing
      return state

    case .addTask(let task):
      state.tasks.append(task)
      return state

    case .deleteTask(let index):
      state.tasks.remove(at: index)
      return state
    } 
  }
}

@devxoul devxoul changed the title [WIP] Moving to Action-State model [WIP] Moving to Action-Mutation-State model Mar 29, 2017
@devxoul devxoul mentioned this pull request Apr 14, 2017
@devxoul devxoul force-pushed the action-state branch 2 times, most recently from f22f206 to ace04aa Compare April 14, 2017 16:20
@devxoul devxoul changed the title [WIP] Moving to Action-Mutation-State model Moving to Action-Mutation-State model Apr 17, 2017
@devxoul devxoul merged commit 09f8252 into master Apr 17, 2017
@devxoul devxoul deleted the action-state branch April 17, 2017 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant