Skip to content

Commit 9dcbfd9

Browse files
authored
Make enum reducer state equatable in tutorial. (#2873)
1 parent 88a46fb commit 9dcbfd9

14 files changed

+204
-117
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extension ContactsFeature {
2+
@Reducer
3+
enum Destination {
4+
case addContact(AddContactFeature)
5+
case alert(AlertState<ContactsFeature.Action.Alert>)
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,7 @@
1-
@Reducer
2-
struct ContactsFeature {
3-
@ObservableState
4-
struct State: Equatable {
5-
var contacts: IdentifiedArrayOf<Contact> = []
6-
@Presents var destination: Destination.State?
7-
}
8-
enum Action {
9-
case addButtonTapped
10-
case deleteButtonTapped(id: Contact.ID)
11-
// case addContact(PresentationAction<AddContactFeature.Action>)
12-
// case alert(PresentationAction<Alert>)
13-
case destination(PresentationAction<Destination.Action>)
14-
enum Alert: Equatable {
15-
case confirmDeletion(id: Contact.ID)
16-
}
17-
}
18-
var body: some ReducerOf<Self> {
19-
Reduce { state, action in
20-
switch action {
21-
case .addButtonTapped:
22-
state.addContact = AddContactFeature.State(
23-
contact: Contact(id: UUID(), name: "")
24-
)
25-
return .none
26-
27-
case let .addContact(.presented(.delegate(.saveContact(contact)))):
28-
state.contacts.append(contact)
29-
return .none
30-
31-
case .addContact:
32-
return .none
33-
34-
case let .alert(.presented(.confirmDeletion(id: id))):
35-
state.contacts.remove(id: id)
36-
return .none
37-
38-
case .alert:
39-
return .none
40-
41-
case let .deleteButtonTapped(id: id):
42-
state.alert = AlertState {
43-
TextState("Are you sure?")
44-
} actions: {
45-
ButtonState(role: .destructive, action: .confirmDeletion(id: id)) {
46-
TextState("Delete")
47-
}
48-
}
49-
return .none
50-
}
51-
}
52-
.ifLet(\.$addContact, action: \.addContact) {
53-
AddContactFeature()
54-
}
55-
.ifLet(\.$alert, action: \.alert)
1+
extension ContactsFeature {
2+
@Reducer(state: .equatable)
3+
enum Destination {
4+
case addContact(AddContactFeature)
5+
case alert(AlertState<ContactsFeature.Action.Alert>)
566
}
577
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
@Reducer
2+
struct ContactsFeature {
3+
@ObservableState
4+
struct State: Equatable {
5+
var contacts: IdentifiedArrayOf<Contact> = []
6+
// @Presents var addContact: AddContactFeature.State?
7+
// @Presents var alert: AlertState<Action.Alert>?
8+
@Presents var destination: Destination.State?
9+
}
10+
enum Action {
11+
case addButtonTapped
12+
case addContact(PresentationAction<AddContactFeature.Action>)
13+
case alert(PresentationAction<Alert>)
14+
case deleteButtonTapped(id: Contact.ID)
15+
enum Alert: Equatable {
16+
case confirmDeletion(id: Contact.ID)
17+
}
18+
}
19+
var body: some ReducerOf<Self> {
20+
Reduce { state, action in
21+
switch action {
22+
case .addButtonTapped:
23+
state.addContact = AddContactFeature.State(
24+
contact: Contact(id: UUID(), name: "")
25+
)
26+
return .none
27+
28+
case let .addContact(.presented(.delegate(.saveContact(contact)))):
29+
state.contacts.append(contact)
30+
return .none
31+
32+
case .addContact:
33+
return .none
34+
35+
case let .alert(.presented(.confirmDeletion(id: id))):
36+
state.contacts.remove(id: id)
37+
return .none
38+
39+
case .alert:
40+
return .none
41+
42+
case let .deleteButtonTapped(id: id):
43+
state.alert = AlertState {
44+
TextState("Are you sure?")
45+
} actions: {
46+
ButtonState(role: .destructive, action: .confirmDeletion(id: id)) {
47+
TextState("Delete")
48+
}
49+
}
50+
return .none
51+
}
52+
}
53+
.ifLet(\.$addContact, action: \.addContact) {
54+
AddContactFeature()
55+
}
56+
.ifLet(\.$alert, action: \.alert)
57+
}
58+
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0005.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ struct ContactsFeature {
88
enum Action {
99
case addButtonTapped
1010
case deleteButtonTapped(id: Contact.ID)
11+
// case addContact(PresentationAction<AddContactFeature.Action>)
12+
// case alert(PresentationAction<Alert>)
1113
case destination(PresentationAction<Destination.Action>)
1214
enum Alert: Equatable {
1315
case confirmDeletion(id: Contact.ID)
@@ -17,10 +19,8 @@ struct ContactsFeature {
1719
Reduce { state, action in
1820
switch action {
1921
case .addButtonTapped:
20-
state.destination = .addContact(
21-
AddContactFeature.State(
22-
contact: Contact(id: UUID(), name: "")
23-
)
22+
state.addContact = AddContactFeature.State(
23+
contact: Contact(id: UUID(), name: "")
2424
)
2525
return .none
2626

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0006.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ struct ContactsFeature {
2424
)
2525
return .none
2626

27-
case let .destination(.presented(.addContact(.delegate(.saveContact(contact))))):
27+
case let .addContact(.presented(.delegate(.saveContact(contact)))):
2828
state.contacts.append(contact)
2929
return .none
3030

31+
case .addContact:
32+
return .none
33+
3134
case let .alert(.presented(.confirmDeletion(id: id))):
3235
state.contacts.remove(id: id)
3336
return .none

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0007.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ struct ContactsFeature {
2828
state.contacts.append(contact)
2929
return .none
3030

31-
case let .destination(.presented(.alert(.confirmDeletion(id: id)))):
31+
case let .alert(.presented(.confirmDeletion(id: id))):
3232
state.contacts.remove(id: id)
3333
return .none
3434

35+
case .alert:
36+
return .none
37+
3538
case let .deleteButtonTapped(id: id):
3639
state.alert = AlertState {
3740
TextState("Are you sure?")

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0008.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ struct ContactsFeature {
3232
state.contacts.remove(id: id)
3333
return .none
3434

35-
case .destination:
36-
return .none
37-
3835
case let .deleteButtonTapped(id: id):
3936
state.alert = AlertState {
4037
TextState("Are you sure?")

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0009.swift

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,13 @@ struct ContactsFeature {
3636
return .none
3737

3838
case let .deleteButtonTapped(id: id):
39-
state.destination = .alert(
40-
AlertState {
41-
TextState("Are you sure?")
42-
} actions: {
43-
ButtonState(role: .destructive, action: .confirmDeletion(id: id)) {
44-
TextState("Delete")
45-
}
39+
state.alert = AlertState {
40+
TextState("Are you sure?")
41+
} actions: {
42+
ButtonState(role: .destructive, action: .confirmDeletion(id: id)) {
43+
TextState("Delete")
4644
}
47-
)
45+
}
4846
return .none
4947
}
5048
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0010.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ struct ContactsFeature {
4848
return .none
4949
}
5050
}
51-
.ifLet(\.$destination, action: \.destination)
51+
.ifLet(\.$addContact, action: \.addContact) {
52+
AddContactFeature()
53+
}
54+
.ifLet(\.$alert, action: \.alert)
5255
}
5356
}
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,53 @@
1-
struct ContactsView: View {
2-
@Bindable var store: StoreOf<ContactsFeature>
3-
4-
var body: some View {
5-
NavigationStack {
6-
List {
7-
ForEach(store.contacts) { contact in
8-
HStack {
9-
Text(contact.name)
10-
Spacer()
11-
Button {
12-
store.send(.deleteButtonTapped(id: contact.id))
13-
} label: {
14-
Image(systemName: "trash")
15-
.foregroundColor(.red)
1+
@Reducer
2+
struct ContactsFeature {
3+
@ObservableState
4+
struct State: Equatable {
5+
var contacts: IdentifiedArrayOf<Contact> = []
6+
@Presents var destination: Destination.State?
7+
}
8+
enum Action {
9+
case addButtonTapped
10+
case deleteButtonTapped(id: Contact.ID)
11+
case destination(PresentationAction<Destination.Action>)
12+
enum Alert: Equatable {
13+
case confirmDeletion(id: Contact.ID)
14+
}
15+
}
16+
var body: some ReducerOf<Self> {
17+
Reduce { state, action in
18+
switch action {
19+
case .addButtonTapped:
20+
state.destination = .addContact(
21+
AddContactFeature.State(
22+
contact: Contact(id: UUID(), name: "")
23+
)
24+
)
25+
return .none
26+
27+
case let .destination(.presented(.addContact(.delegate(.saveContact(contact))))):
28+
state.contacts.append(contact)
29+
return .none
30+
31+
case let .destination(.presented(.alert(.confirmDeletion(id: id)))):
32+
state.contacts.remove(id: id)
33+
return .none
34+
35+
case .destination:
36+
return .none
37+
38+
case let .deleteButtonTapped(id: id):
39+
state.destination = .alert(
40+
AlertState {
41+
TextState("Are you sure?")
42+
} actions: {
43+
ButtonState(role: .destructive, action: .confirmDeletion(id: id)) {
44+
TextState("Delete")
1645
}
1746
}
18-
}
19-
}
20-
.navigationTitle("Contacts")
21-
.toolbar {
22-
ToolbarItem {
23-
Button {
24-
store.send(.addButtonTapped)
25-
} label: {
26-
Image(systemName: "plus")
27-
}
28-
}
29-
}
30-
}
31-
.sheet(
32-
item: $store.scope(state: \.destination?.addContact, action: \.destination.addContact)
33-
) { addContactStore in
34-
NavigationStack {
35-
AddContactView(store: addContactStore)
47+
)
48+
return .none
3649
}
3750
}
38-
.alert($store.scope(state: \.alert, action: \.alert))
51+
.ifLet(\.$destination, action: \.destination)
3952
}
4053
}

0 commit comments

Comments
 (0)