Skip to content

Commit c36d8ce

Browse files
Clean up shared state case study (#2696)
* Clean up shared state case study. * wip * wip * Update Examples/CaseStudies/SwiftUICaseStudies/01-GettingStarted-SharedState.swift --------- Co-authored-by: Stephen Celis <[email protected]>
1 parent 97304ef commit c36d8ce

File tree

2 files changed

+138
-137
lines changed

2 files changed

+138
-137
lines changed

Examples/CaseStudies/SwiftUICaseStudies/01-GettingStarted-SharedState.swift

Lines changed: 113 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -18,44 +18,44 @@ private let readMe = """
1818

1919
@Reducer
2020
struct SharedState {
21-
enum Tab { case counter, profile }
21+
enum Tab { case stats, profile }
2222

2323
struct State: Equatable {
24-
var counter = Counter.State()
25-
var currentTab = Tab.counter
24+
var currentTab = Tab.stats
25+
var stats = Stats.State()
2626

27-
/// The Profile.State can be derived from the Counter.State by getting and setting the parts it
27+
/// The Profile.State can be derived from the Stats.State by getting and setting the parts it
2828
/// cares about. This allows the profile feature to operate on a subset of app state instead of
2929
/// the whole thing.
3030
var profile: Profile.State {
3131
get {
3232
Profile.State(
3333
currentTab: self.currentTab,
34-
count: self.counter.count,
35-
maxCount: self.counter.maxCount,
36-
minCount: self.counter.minCount,
37-
numberOfCounts: self.counter.numberOfCounts
34+
count: self.stats.count,
35+
maxCount: self.stats.maxCount,
36+
minCount: self.stats.minCount,
37+
numberOfCounts: self.stats.numberOfCounts
3838
)
3939
}
4040
set {
4141
self.currentTab = newValue.currentTab
42-
self.counter.count = newValue.count
43-
self.counter.maxCount = newValue.maxCount
44-
self.counter.minCount = newValue.minCount
45-
self.counter.numberOfCounts = newValue.numberOfCounts
42+
self.stats.count = newValue.count
43+
self.stats.maxCount = newValue.maxCount
44+
self.stats.minCount = newValue.minCount
45+
self.stats.numberOfCounts = newValue.numberOfCounts
4646
}
4747
}
4848
}
4949

5050
enum Action {
51-
case counter(Counter.Action)
5251
case profile(Profile.Action)
5352
case selectTab(Tab)
53+
case stats(Stats.Action)
5454
}
5555

5656
var body: some Reducer<State, Action> {
57-
Scope(state: \.counter, action: \.counter) {
58-
Counter()
57+
Scope(state: \.stats, action: \.stats) {
58+
Stats()
5959
}
6060

6161
Scope(state: \.profile, action: \.profile) {
@@ -64,99 +64,14 @@ struct SharedState {
6464

6565
Reduce { state, action in
6666
switch action {
67-
case .counter, .profile:
67+
case .profile, .stats:
6868
return .none
6969
case let .selectTab(tab):
7070
state.currentTab = tab
7171
return .none
7272
}
7373
}
7474
}
75-
76-
@Reducer
77-
struct Counter {
78-
struct State: Equatable {
79-
@PresentationState var alert: AlertState<Action.Alert>?
80-
var count = 0
81-
var maxCount = 0
82-
var minCount = 0
83-
var numberOfCounts = 0
84-
}
85-
86-
enum Action {
87-
case alert(PresentationAction<Alert>)
88-
case decrementButtonTapped
89-
case incrementButtonTapped
90-
case isPrimeButtonTapped
91-
92-
enum Alert: Equatable {}
93-
}
94-
95-
var body: some Reducer<State, Action> {
96-
Reduce { state, action in
97-
switch action {
98-
case .alert:
99-
return .none
100-
101-
case .decrementButtonTapped:
102-
state.count -= 1
103-
state.numberOfCounts += 1
104-
state.minCount = min(state.minCount, state.count)
105-
return .none
106-
107-
case .incrementButtonTapped:
108-
state.count += 1
109-
state.numberOfCounts += 1
110-
state.maxCount = max(state.maxCount, state.count)
111-
return .none
112-
113-
case .isPrimeButtonTapped:
114-
state.alert = AlertState {
115-
TextState(
116-
isPrime(state.count)
117-
? "👍 The number \(state.count) is prime!"
118-
: "👎 The number \(state.count) is not prime :("
119-
)
120-
}
121-
return .none
122-
}
123-
}
124-
.ifLet(\.$alert, action: \.alert)
125-
}
126-
}
127-
128-
@Reducer
129-
struct Profile {
130-
struct State: Equatable {
131-
private(set) var currentTab: Tab
132-
private(set) var count = 0
133-
private(set) var maxCount: Int
134-
private(set) var minCount: Int
135-
private(set) var numberOfCounts: Int
136-
137-
fileprivate mutating func resetCount() {
138-
self.currentTab = .counter
139-
self.count = 0
140-
self.maxCount = 0
141-
self.minCount = 0
142-
self.numberOfCounts = 0
143-
}
144-
}
145-
146-
enum Action {
147-
case resetCounterButtonTapped
148-
}
149-
150-
var body: some Reducer<State, Action> {
151-
Reduce { state, action in
152-
switch action {
153-
case .resetCounterButtonTapped:
154-
state.resetCount()
155-
return .none
156-
}
157-
}
158-
}
159-
}
16075
}
16176

16277
// MARK: - Feature view
@@ -170,22 +85,22 @@ struct SharedStateView: View {
17085
WithViewStore(self.store, observe: \.currentTab) { viewStore in
17186
VStack {
17287
Picker("Tab", selection: viewStore.binding(send: { .selectTab($0) })) {
173-
Text("Counter")
174-
.tag(SharedState.Tab.counter)
88+
Text("Stats")
89+
.tag(SharedState.Tab.stats)
17590

17691
Text("Profile")
17792
.tag(SharedState.Tab.profile)
17893
}
17994
.pickerStyle(.segmented)
18095

181-
if viewStore.state == .counter {
182-
SharedStateCounterView(
183-
store: self.store.scope(state: \.counter, action: \.counter)
96+
if viewStore.state == .stats {
97+
StatsView(
98+
store: self.store.scope(state: \.stats, action: \.stats)
18499
)
185100
}
186101

187102
if viewStore.state == .profile {
188-
SharedStateProfileView(
103+
ProfileView(
189104
store: self.store.scope(state: \.profile, action: \.profile)
190105
)
191106
}
@@ -197,8 +112,8 @@ struct SharedStateView: View {
197112
}
198113
}
199114

200-
struct SharedStateCounterView: View {
201-
let store: StoreOf<SharedState.Counter>
115+
private struct StatsView: View {
116+
let store: StoreOf<Stats>
202117

203118
var body: some View {
204119
WithViewStore(self.store, observe: { $0 }) { viewStore in
@@ -233,8 +148,8 @@ struct SharedStateCounterView: View {
233148
}
234149
}
235150

236-
struct SharedStateProfileView: View {
237-
let store: StoreOf<SharedState.Profile>
151+
private struct ProfileView: View {
152+
let store: StoreOf<Profile>
238153

239154
var body: some View {
240155
WithViewStore(self.store, observe: { $0 }) { viewStore in
@@ -256,7 +171,7 @@ struct SharedStateProfileView: View {
256171
Text("Max count: \(viewStore.maxCount)")
257172
Text("Min count: \(viewStore.minCount)")
258173
Text("Total number of count events: \(viewStore.numberOfCounts)")
259-
Button("Reset") { viewStore.send(.resetCounterButtonTapped) }
174+
Button("Reset") { viewStore.send(.resetStatsButtonTapped) }
260175
}
261176
}
262177
.padding(.top)
@@ -288,3 +203,89 @@ private func isPrime(_ p: Int) -> Bool {
288203
}
289204
return true
290205
}
206+
207+
208+
@Reducer
209+
struct Stats {
210+
struct State: Equatable {
211+
@PresentationState var alert: AlertState<Action.Alert>?
212+
var count = 0
213+
var maxCount = 0
214+
var minCount = 0
215+
var numberOfCounts = 0
216+
}
217+
218+
enum Action {
219+
case alert(PresentationAction<Alert>)
220+
case decrementButtonTapped
221+
case incrementButtonTapped
222+
case isPrimeButtonTapped
223+
224+
enum Alert: Equatable {}
225+
}
226+
227+
var body: some Reducer<State, Action> {
228+
Reduce { state, action in
229+
switch action {
230+
case .alert:
231+
return .none
232+
233+
case .decrementButtonTapped:
234+
state.count -= 1
235+
state.numberOfCounts += 1
236+
state.minCount = min(state.minCount, state.count)
237+
return .none
238+
239+
case .incrementButtonTapped:
240+
state.count += 1
241+
state.numberOfCounts += 1
242+
state.maxCount = max(state.maxCount, state.count)
243+
return .none
244+
245+
case .isPrimeButtonTapped:
246+
state.alert = AlertState {
247+
TextState(
248+
isPrime(state.count)
249+
? "👍 The number \(state.count) is prime!"
250+
: "👎 The number \(state.count) is not prime :("
251+
)
252+
}
253+
return .none
254+
}
255+
}
256+
.ifLet(\.$alert, action: \.alert)
257+
}
258+
}
259+
260+
@Reducer
261+
struct Profile {
262+
struct State: Equatable {
263+
private(set) var currentTab: SharedState.Tab
264+
private(set) var count = 0
265+
private(set) var maxCount: Int
266+
private(set) var minCount: Int
267+
private(set) var numberOfCounts: Int
268+
269+
fileprivate mutating func resetCount() {
270+
self.currentTab = .stats
271+
self.count = 0
272+
self.maxCount = 0
273+
self.minCount = 0
274+
self.numberOfCounts = 0
275+
}
276+
}
277+
278+
enum Action {
279+
case resetStatsButtonTapped
280+
}
281+
282+
var body: some Reducer<State, Action> {
283+
Reduce { state, action in
284+
switch action {
285+
case .resetStatsButtonTapped:
286+
state.resetCount()
287+
return .none
288+
}
289+
}
290+
}
291+
}

0 commit comments

Comments
 (0)