여기까지 오셨다면 이제 여러분들은 Reducer를 통해 Store를 생성해 View에 출력하는 방법을 모두 익히신겁니다. 하지만 이전보다 앱이 복잡해지고 규모가 커진다면 하나의 Reducer
에서 상태관리를 하기에는 힘이 들기 마련입니다. 이럴 땐 Reducer
를 특정 작업을 수행하도록 작게 나눌 수
있습니다.
<aside> 💡 MultiStore는 다음과 같은 강점을 가집니다.
자식 state의 부재를 UI에서 우아하게 처리할 수 있습니다.
작게 나눈 자식 Reducer는 독립적으로 작동하고 관리될 수 있습니다.
특정 부분만 업데이트하고 싶을 때 해당 부분의 작은 store를 통해 성능을 최적화 할 수 있습니다.
</aside>
MultiStore에서는 부모가 자식의 State를 보유하고 있으며 자식 State가 optional일때, 배열일 때, enum일 때 Reducer를 결합
하고 이를 View에 출력하는 방법을 소개합니다.
즉, 부모의 기능이 자식 State를 Optional
로 가지고 있는 경우 사용할 수 있습니다.
다음 부모가 optional한 자식의 State를 보유하고 있으며, 부모의 Reducer에 ifLet을 달아 자식의 Action을 감지하고 있다가 자식의 State가 non optional일 때
자식의 Reducer를 실행
하는 간단한 예제입니다.
struct Parent: Reducer {
struct State {
var child: Child.State?
/* code */
}
enum Action {
case child(Child.Action)
/* code */
}
var body: some Reducer<State, Action> {
Reduce { state, action in
}
.ifLet(\\.child, action: /Action.child) {
Child()
}
}
}
@warn_unqualified_access func ifLet<WrappedState, WrappedAction, Wrapped>(
_ toWrappedState: WritableKeyPath<Self.State, WrappedState?>,
action toWrappedAction: CasePath<Self.Action, WrappedAction>,
@ReducerBuilder<WrappedState, WrappedAction>
then wrapped: () -> Wrapped,
fileID: StaticString = #fileID,
line: UInt = #line
) -> _IfLetReducer<Self, Wrapped>
where WrappedState == Wrapped.State,
WrappedAction == Wrapped.Action,
Wrapped : Reducer
매개변수
toWrappedState
: 부모의 State 에서 optional 자식 State 를 포함하는 쓰기 가능한 키 경로입니다.toWrappedAction
: 부모 Action에서 자식 Action을 포함하는 케이스 경로입니다.wrapped
: non-optional인 자식 State 에 대해 자식 Action과 함께 호출될 Reducer입니다.반환값 (_IfLetReducer<Self, Wrapped>)
where절은 다음과 같이 작동하고 있습니다.
→ 3 가지를 만족했을 때 부모 Reducer와 자식 Reducer를 조합한 새로운 Reducer를 반환합니다.