Skip to content

Commit 3ca8249

Browse files
authored
Coalesce synchronous effectful mutations to state (#619)
1 parent e7e222f commit 3ca8249

File tree

2 files changed

+13
-24
lines changed

2 files changed

+13
-24
lines changed

Sources/ComposableArchitecture/Store.swift

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ public final class Store<State, Action> {
119119
private var isSending = false
120120
private var parentCancellable: AnyCancellable?
121121
private let reducer: (inout State, Action) -> Effect<Action, Never>
122-
private var synchronousActionsToSend: [Action] = []
123122
private var bufferedActions: [Action] = []
124123

125124
/// Initializes a store from an initial state, a reducer, and an environment.
@@ -367,41 +366,31 @@ public final class Store<State, Action> {
367366
}
368367

369368
func send(_ action: Action) {
370-
if !self.isSending {
371-
self.synchronousActionsToSend.append(action)
372-
} else {
373-
self.bufferedActions.append(action)
374-
return
375-
}
376-
377-
while !self.synchronousActionsToSend.isEmpty || !self.bufferedActions.isEmpty {
378-
let action =
379-
!self.synchronousActionsToSend.isEmpty
380-
? self.synchronousActionsToSend.removeFirst()
381-
: self.bufferedActions.removeFirst()
369+
self.bufferedActions.append(action)
370+
guard !self.isSending else { return }
382371

383-
self.isSending = true
384-
let effect = self.reducer(&self.state.value, action)
372+
self.isSending = true
373+
var currentState = self.state.value
374+
defer {
375+
self.state.value = currentState
385376
self.isSending = false
377+
}
378+
379+
while !self.bufferedActions.isEmpty {
380+
let action = self.bufferedActions.removeFirst()
381+
let effect = self.reducer(&currentState, action)
386382

387383
var didComplete = false
388384
let uuid = UUID()
389-
390-
var isProcessingEffects = true
391385
let effectCancellable = effect.sink(
392386
receiveCompletion: { [weak self] _ in
393387
didComplete = true
394388
self?.effectCancellables[uuid] = nil
395389
},
396390
receiveValue: { [weak self] action in
397-
if isProcessingEffects {
398-
self?.synchronousActionsToSend.append(action)
399-
} else {
400-
self?.send(action)
401-
}
391+
self?.send(action)
402392
}
403393
)
404-
isProcessingEffects = false
405394

406395
if !didComplete {
407396
self.effectCancellables[uuid] = effectCancellable

Tests/ComposableArchitectureTests/StoreTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,6 @@ final class StoreTests: XCTestCase {
434434

435435
viewStore.send(0)
436436

437-
XCTAssertEqual(emissions, [0, 1, 2, 3])
437+
XCTAssertEqual(emissions, [0, 3])
438438
}
439439
}

0 commit comments

Comments
 (0)