How to use tab view selection properly? #1849
-
I have created a reducer with a bindable state of selected tab. It works if I set Also, if I select tab from this test action What might I be missing there? 🤔 struct CreateReducer: ReducerProtocol {
struct State: Equatable {
var navigationTitle: String
}
enum Action {
case refresh
}
var body: some ReducerProtocol<State, Action> {
Reduce { state, action in
switch action {
case .refresh:
return .none
}
}
}
}
// MARK: - Initial state
extension CreateReducer.State {
static var initial: Self {
@Dependency(\.localizer.create) var localizer;
return .init(navigationTitle: localizer.navigationTitle)
}
} struct HomeReducer: ReducerProtocol {
struct State: Equatable {
var navigationTitle: String
}
enum Action {
case refresh
}
var body: some ReducerProtocol<State, Action> {
Reduce { state, action in
switch action {
case .refresh:
return .none
}
}
}
}
// MARK: - Initial state
extension HomeReducer.State {
static var initial: Self {
@Dependency(\.localizer.home) var localizer;
return .init(navigationTitle: localizer.navigationTitle)
}
} struct RootReducer: ReducerProtocol {
struct State: Equatable {
var home: Identified<Tab, HomeReducer.State>
var create: Identified<Tab, CreateReducer.State>
@BindableState var selectedTab: Tab
}
enum Action: BindableAction {
case binding(BindingAction<State>)
case home(HomeReducer.Action)
case create(CreateReducer.Action)
case selectTab(State.Tab)
}
var body: some ReducerProtocol<State, Action> {
BindingReducer()
Reduce { state, action in
switch action {
case let .selectTab(tab):
state.selectedTab = tab
return .none
// case .binding(\.$selectedTab):
// print(state.selectedTab)
// return .none
default:
return .none
}
}
Scope(state: \.home.value, action: /Action.home) {
HomeReducer()
}
Scope(state: \.create.value, action: /Action.create) {
CreateReducer()
}
}
}
// MARK: - Initial state
extension RootReducer.State {
static var initial: Self {
.init(
home: .init(.initial, id: .home),
create: .init(.initial, id: .create),
selectedTab: .home
)
}
}
// MARK: - Tab item
extension RootReducer.State {
enum Tab: String, Identifiable {
case home, create
var id: Self { self }
}
} struct RootView: View {
// MARK: - Typealias
typealias Reducer = RootReducer
// MARK: - Properties
private let viewStore: ViewStoreOf<Reducer>
// MARK: - Init
init(store: StoreOf<Reducer>) {
viewStore = .init(store, observe: { $0 })
}
// MARK: - Body
var body: some View {
ZStack(alignment: .top) {
TabView(selection: viewStore.binding(\.$selectedTab)) {
NavigationStack {
Text("Home placeholder")
.navigationTitle(viewStore.home.navigationTitle)
}
.tabItem {
Label("Home", systemImage: "house")
}
.tag(viewStore.home.id)
NavigationStack {
Text("Create placeholder")
.navigationTitle(viewStore.create.navigationTitle)
}
.tabItem {
Label("Create", systemImage: "plus.square")
}
.tag(viewStore.create.id)
}
VStack {
Text("Selection: \(viewStore.selectedTab.rawValue)")
Button("Test Select", action: {
viewStore.send(.selectTab(.create))
})
}
}
.onChange(of: viewStore.selectedTab) { newValue in
print(newValue)
}
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hi @kakhaberikiknadze, this is happening because your -private let viewStore: ViewStoreOf<Reducer>
+@ObservedObject var viewStore: ViewStoreOf<Reducer> |
Beta Was this translation helpful? Give feedback.
Hi @kakhaberikiknadze, this is happening because your
viewStore
is installed into the view as a regularlet
and not an@ObservedObject
: