앱/SwiftUI
SwiftUI) TCA- Effect에 대해서
진ddang
2024. 9. 17. 04:42
Effect는 Action을 통해서 동작할 동작들을 의미한다.
Effect에는 다음과 같은 동작들이 존재한다 .
- none: 즉시 완료
- run: 비동기 작업
- send: 전달된 Action을 즉시 내보냄
- cancel: 진행중인 Effect를 취소
- merge: 동시에 실행되는 단일 Effect로 병합
- concatenate: 차례로 실행되는 단일 Effect로 연결
- animation: SwiftUI의 .withAnimation
- transcation: SwiftUI의 .withTransaction
- debounce: debounce Effect로 변경
- throttle: trottle Effect로 변경
Effect는 기본적으로 단일의 행동을 하도록 하고, 여러 동작을 묶을수도 있으며, 연쇄적으로 동작할수도 있다.
예시 )
Reduce { state, action in
switch action {
case .onAppear:
return .concatenate([
.send(.request)
])
case .request:
return .run { send in
let response = await newsClient.request()
await send(.fetchResponse(response))
}
case let .fetchResponse(.success(newses)):
state.newses = newses
return .none
default:
return .none
}
Concatenate와 같은 타입 사용법
기존의 .none과 .run처럼 두개의 액션을 동시에 처리하거나, 순서대로 처리하거나 하는 동작에서
.merge와 .concat과 같은 방식으로 처리를 할수 있음
예시코드
Reduce { state, action in
switch action {
case .onAppear:
return .concatenate([
.send(.someActionFirst)
.send(.someActionAfter)
])
}
액션에 따른 Effect를 묶어주고, 해당 이펙트들이 다시 액션에서 동작하도록 묶어주는 역할을 하게 된다.
이를 통해서 api호출의 순서를 보장하거나, UI 업데이트의 순서를 보장하거나 할 수 있다.
자주 보는 에러
run 안에서는 state를 캡처링 할수 없기 때문에
case .factButtonTapped:
state.fact = nil
state.isLoading = true
let (data, _) = try await URLSession.shared
.data(from: URL(string: "<http://numbersapi.com/\\\\(state.count)>")!)
// 🛑 'async' call in a function that does not support concurrency
// 🛑 Errors thrown from here are not handled
state.fact = String(decoding: data, as: UTF8.self)
state.isLoading = false
return .none
이렇게 직접적으로 state의 값을 변경하려고 하면 에러가 발생한다 .
따라서 새로이 action을 정의하고, 해당 액션 안에서 받은 데이터를 통해서 State를 다시 업데이트 해주는 방식으로 처리해야한다.
해결방법 코드
case .factButtonTapped:
state.fact = nil
state.isLoading = true
return .run { send in
let (data, _) = try await URLSession.shared
.data(from: URL(string: "<http://numbersapi.com/\\\\(state.count)>")!)
let fact = String(decoding: data, as: UTF8.self)
send(.fetchData(fact)
}
case let .fetchData(fact):
state.fact = fact
state.isLoading = false
return .none
반응형