본문 바로가기
iOS/ReactorKit

[ReactorKit] transform과 global state에 대하여

by 최지철 2024. 8. 5.
728x90
반응형

Transform

func transform(action: Observable<Action>) -> Observable<Action>
func transform(mutation: Observable<Mutation>) -> Observable<Mutation>
func transform(state: Observable<State>) -> Observable<State>

Transform의 함수 종류는 총 3개가 있다.

 

transform 함수는 개발자가 Action, State 및 Mutation 스트림을 조작할 수 있게 해준다.

  • 부작용 처리: 로깅, 분석 또는 네트워크 요청과 같은 부작용 처리.
  • 복잡한 반응형 흐름 구성: 여러 작업을 체이닝하여 구성.
  • 액션 및 상태 필터링 또는 수정: 더 예측 가능한 상태 관리 흐름을 만들기 위해.
  • Global State와의 상호작용: 여러 Reactor가 공통 상태를 공유하고 관리

transform 함수는 세 가지 주요 변환 포인트를 제공한다.:

  1. transform(action:): 들어오는 action을 바로 가로채서 변환할 수 있다.
  2. transform(mutation:): 들어오는 mutation을 바로 가로채서 변환할 수 있다.
  3. transform(state:): 들어오는 state 스트림을 바로  가로채서 변환할 수 있다.

Global States

Redux와 달리 ReactorKit은 글로벌 앱 상태를 정의하지 않는다.

 

ReactorKit의 흐름은 일반적으로, Action → Mutation → State 이다.

그렇다는 것은 즉, global state를 정의하기 위해 어떠한 방법이든 자유롭게 사용 가능하다는것과

global state를 사용하기 위해 BehaviorSubject, PublishSubject 심지어는 reactor를 사용할 수 있음을 의미한다.
ReactorKit은 앱에서 특정 기능을 위해 global state를 강요하지 않는다.

 

그렇다면, Global State는 뭐고, 어떻게 활용할까?

 

global State는  여러 Reactor에서 이 subject의 value가 변할때마다 알림을 받거나 사용자 정보에 접근하고 싶어하는 경우를 예로 들 수 있다.

var currentUser: BehaviorSubject<User> // global state

func transform(mutation: Observable<Mutation>) -> Observable<Mutation> {
  return Observable.merge(mutation, currentUser.map(Mutation.setUser))

 transform() 은 Action 없이도 Mutation이 가능하도록 도와주는 함수이다.

 

이를 통해 화면간 데이터 전달 또한 가능하다.

 

import UIKit
import ReactorKit
import RxSwift
import RxCocoa

class MainViewController: UIViewController, View {
    var disposeBag = DisposeBag()
    let textField = UITextField()
    let submitButton = UIButton()
    
    init(reactor: MainReactor) {
        super.init(nibName: nil, bundle: nil)
        self.reactor = reactor
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // UI 설정
        view.addSubview(textField)
        view.addSubview(submitButton)
        
        // 레이아웃 설정 (생략)
    }

    func bind(reactor: MainReactor) {
        // 액션 바인딩
        submitButton.rx.tap
            .map { Reactor.Action.submitText(self.textField.text ?? "") }
            .bind(to: reactor.action)
            .disposed(by: disposeBag)
    }
}
class MainReactor: Reactor {
    enum Action {
        case submitText(String)
    }
    
    enum Mutation {
        case setText(String)
    }
    
    struct State {
        var text: String = ""
    }
    
    let initialState = State()
    
    func mutate(action: Action) -> Observable<Mutation> {
        switch action {
        case .submitText(let text):
            return Observable.just(Mutation.setText(text))
        }
    }
    
    func reduce(state: State, mutation: Mutation) -> State {
        var newState = state
        switch mutation {
        case .setText(let text):
            newState.text = text
        }
        return newState
    }
    
    func transform(mutation: Observable<Mutation>) -> Observable<Mutation> {
        return mutation.do(onNext: { mutation in
            switch mutation {
            case .setText(let text):
                AppState.shared.sharedText = text
            }
        })
    }
}
728x90
반응형

'iOS > ReactorKit' 카테고리의 다른 글

[ReactortKit] ReactortKit 슥 알아보기  (1) 2024.06.09