LoginSignup
0
0

More than 3 years have passed since last update.

ReactorKitでFirestoreをListenする方法

Posted at

概要

ReactorKitを使ったプロジェクトでFirestoreを使うことになったので、Pringを用いて実装しました。

環境

実装

UserというモデルをFirestoreから取得してくるという設定です。

Reactor側

Action, Mutation, State, mutate, reduceはやるだけって感じです。
ポイントはdataSourceを以下のように用意して、

private let dataSource: DataSource<User>?

setupDataSource()内でDataSourcelisten()してやることです。
この時.onの中でself?.action.onNext(.updateUsers(users))することで、Firestoreから取得したデータをReactorのストリームにうまく取り込んでます。

private func setupDataSource() {
    dataSource = User.query.dataSource()
        .on { [weak self] _, _ in
            guard let users = self?.dataSource?.documents else { return }
            self?.action.onNext(.updateUsers(users))
        }
        .listen()
}

全実装は以下のようになります。

import ReactorKit
import RxSwift
import Pring

final class UserListReactor: Reactor {
    enum Action {
        case updateUsers([User])
    }

    enum Mutation {
        case setUsers([User])
    }

    struct State {
        var users: [User] = []
    }

    // MARK: - Variables

    let initialState = State()
    private let dataSource: DataSource<User>?

    // MARK: - Initializer

    init() {
        setupDataSource()
    }

    // MARK: - Setup Methods

    private func setupDataSource() {
        dataSource = User.query.dataSource()
            .on { [weak self] _, _ in
                guard let users = self?.dataSource?.documents else { return }
                self?.action.onNext(.updateUsers(users))
            }
            .listen()
    }

    // MARK: - Reactor Methods

    func mutate(action: Action) -> Observable<Mutation> {
        switch action {
        case let .updateUsers(users):
            return .just(Mutation.setUsers(users))
        }
    }

    func reduce(state: State, mutation: Mutation) -> State {
        var state = state
        switch mutation {
        case let .setUsers(users):
            state.users = users
        }
        return state
    }
}

ViewController側

いつも通りbind(reactor:)内でUserListReactor.State.usersbindしてやれば終わりです。

import UIKit
import RxSwift
import ReactorKit

final class UserListViewController: UIViewController, View {
    // MARK: - Variables

    var disposeBag = DisposeBag()
    ...
    // MARK: - Bind Methods

    func bind(reactor: UserListReactor) {
        // State
        reactor.state.map { $0.users }
            .distinctUntilChanged()
            .bind { users in
                // tableView or collectionViewの更新
            }
            .disposed(by: disposeBag)
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0