admin管理员组文章数量:1310221
I would like to make reusable solution to avoid boilerplate for lazy loading features
I have base state and base view model which describes common
@ObservableState
enum BaseState<Input, BaseContentState> {
case progress(BaseProgressState<Input>)
case content(BaseContentState)
case error(BaseErrorState<Input>)
init(input: Input) {
self = .progress(BaseProgressState(input: input))
}
}
@Reducer
struct BaseViewModel<Input, ContentInput, BaseContentState: BaseContentStateType, BaseContentAction> where ContentInput == BaseContentState.ContentInput {
typealias State = BaseState<Input, BaseContentState>
enum Action {
case progress(BaseProgressAction<Input, ContentInput>)
case content(BaseContentAction)
case error(BaseErrorAction<Input>)
}
}
BaseContentStateType
allows to make content state buildable with some result of progress feature
protocol BaseContentStateType {
associatedtype ContentInput
init(contentInput: ContentInput)
}
Additional I have common implementation to show progress...
@ObservableState
struct BaseProgressState<Input> {
let input: Input
}
enum BaseProgressAction<Input, ContentInput> {
case load(Input)
case loadSuccess(ContentInput)
case loadFailure(Input, Error)
}
struct BaseProgressViewModel<Input, ContentInput>: Reducer {
typealias State = BaseProgressState<Input>
typealias Action = BaseProgressAction<Input, ContentInput>
var body: some ReducerOf<Self> {
EmptyReducer()
}
}
struct BaseProgressView<Input, ContentInput>: View {
let store: StoreOf<BaseProgressViewModel<Input, ContentInput>>
var body: some View {
ProgressView()
.onAppear {
store.send(.load(store.input))
}
}
}
... and error
@ObservableState
struct BaseErrorState<Input> {
let input: Input
let error: Error
}
enum BaseErrorAction<Input> {
case retry(Input)
}
struct BaseErrorViewModel<Input>: Reducer {
typealias State = BaseErrorState<Input>
typealias Action = BaseErrorAction<Input>
var body: some ReducerOf<Self> {
EmptyReducer()
}
}
struct BaseErrorView<Input>: View {
let store: StoreOf<BaseErrorViewModel<Input>>
var body: some View {
Button("Retry") {
store.send(.retry(store.input))
}
}
}
When I try to use this solution...
@Reducer
struct FeatureViewModel {
typealias State = BaseViewModel<...>.State
typealias Action = BaseViewModel<...>.Action
var body: some ReducerOf<Self> {
...
}
}
struct FeatureView: View {
let store: StoreOf<FeatureViewModel>
var body: some View {
BaseView(store: store) { store in
FeatureContentView(store: store)
}
}
}
... I face problems, like
Instance method 'ifLet(_:action:)' requires that 'FeatureViewModel.State' (aka 'BaseState<FeatureInput, FeatureContentViewModel.State>') conform to 'CaseReducerState'
And no matter how hard I try to get it to look right, I don't understand what I'm doing wrong. How to confirm CaseReducerState
?
I would like to make reusable solution to avoid boilerplate for lazy loading features
I have base state and base view model which describes common
@ObservableState
enum BaseState<Input, BaseContentState> {
case progress(BaseProgressState<Input>)
case content(BaseContentState)
case error(BaseErrorState<Input>)
init(input: Input) {
self = .progress(BaseProgressState(input: input))
}
}
@Reducer
struct BaseViewModel<Input, ContentInput, BaseContentState: BaseContentStateType, BaseContentAction> where ContentInput == BaseContentState.ContentInput {
typealias State = BaseState<Input, BaseContentState>
enum Action {
case progress(BaseProgressAction<Input, ContentInput>)
case content(BaseContentAction)
case error(BaseErrorAction<Input>)
}
}
BaseContentStateType
allows to make content state buildable with some result of progress feature
protocol BaseContentStateType {
associatedtype ContentInput
init(contentInput: ContentInput)
}
Additional I have common implementation to show progress...
@ObservableState
struct BaseProgressState<Input> {
let input: Input
}
enum BaseProgressAction<Input, ContentInput> {
case load(Input)
case loadSuccess(ContentInput)
case loadFailure(Input, Error)
}
struct BaseProgressViewModel<Input, ContentInput>: Reducer {
typealias State = BaseProgressState<Input>
typealias Action = BaseProgressAction<Input, ContentInput>
var body: some ReducerOf<Self> {
EmptyReducer()
}
}
struct BaseProgressView<Input, ContentInput>: View {
let store: StoreOf<BaseProgressViewModel<Input, ContentInput>>
var body: some View {
ProgressView()
.onAppear {
store.send(.load(store.input))
}
}
}
... and error
@ObservableState
struct BaseErrorState<Input> {
let input: Input
let error: Error
}
enum BaseErrorAction<Input> {
case retry(Input)
}
struct BaseErrorViewModel<Input>: Reducer {
typealias State = BaseErrorState<Input>
typealias Action = BaseErrorAction<Input>
var body: some ReducerOf<Self> {
EmptyReducer()
}
}
struct BaseErrorView<Input>: View {
let store: StoreOf<BaseErrorViewModel<Input>>
var body: some View {
Button("Retry") {
store.send(.retry(store.input))
}
}
}
When I try to use this solution...
@Reducer
struct FeatureViewModel {
typealias State = BaseViewModel<...>.State
typealias Action = BaseViewModel<...>.Action
var body: some ReducerOf<Self> {
...
}
}
struct FeatureView: View {
let store: StoreOf<FeatureViewModel>
var body: some View {
BaseView(store: store) { store in
FeatureContentView(store: store)
}
}
}
... I face problems, like
Instance method 'ifLet(_:action:)' requires that 'FeatureViewModel.State' (aka 'BaseState<FeatureInput, FeatureContentViewModel.State>') conform to 'CaseReducerState'
And no matter how hard I try to get it to look right, I don't understand what I'm doing wrong. How to confirm CaseReducerState
?
- You probably only want a generic and quite "opinionated" State type, which can be composed out of several sub types, where you can represent a rich UI, and which features a lot of convenience accessors and modifiers. – CouchDeveloper Commented Feb 2 at 21:44
1 Answer
Reset to default 0I fot to make ViewModel
for this case
.ifLet(\.$myFeatureState, action: \.myFeatureAction) {
MyFeatureViewModel()
}
本文标签: swiftGeneric state for TCAStack Overflow
版权声明:本文标题:swift - Generic state for TCA - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741838998a2400385.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论