Best way for @Dependency to send action to reducer #1437
-
|
What is the best way to let a dependency notify the reducer that its contents changed? One setup I'm using now is to have a private private let eventsSubject = PassthroughSubject<Event, Never>()
public let eventsEffect: Effect<Event, Never>
init() {
self.eventsEffect = Effect(eventsSubject)
}
// ...
// In reducer
case .launched:
return myDependency.eventsEffect.map(Action.receivedEvent)
case .receivedEvent(Event):
// do somethingSo now for the questions: Is this a good idea or is there a better way? And especially:
Would it be completely crazy to put some common state that often changes and is used by every single leaf view, in the Just FYI, one of the dependencies I need to subscribe to is CoreData, others are my own audio players and similar. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 13 replies
-
|
Since the "concurrency" update, the easiest way to handle this is indeed an case .observeDependency:
return .run { send in
for await value in myDependency.asyncValues {
await send(.receivedEvent(value))
}
}
case let .receivedEvent(value):
// Do whatever you need to do each time the value changes.
state.count = value.count
return .noneNow in the view, you exploit the fact that the Text("Hello!")
.task {
await viewStore.send(.observeDependency).finish()
}So this Subscribing in this way in a hundred of views is very likely a bad idea, as it will generate a considerable traffic of actions for the store. You should probably find a way to pass the udpated value along the states while scoping. It doesn't need to be monolithic, and you can maybe have a few subscriptions that handle a few runs of scoped states if it's more convenient in your case. We would maybe be able to provide more precise feedback with a more explicit use-case. What are your 100 views? rows in a list? |
Beta Was this translation helpful? Give feedback.
-
|
So I don't have either compiler directives, As to AsyncSequence, I do have a publisher in one of the dependencies, but I'd rather make it an AsyncSequence directly. For the others, I haven't added any subscription stuff yet. Haven't found any basic examples of adding AsyncSequence, do you know any? |
Beta Was this translation helpful? Give feedback.
-
|
Actually it's more like So maybe it's all these geometry readers that confuse SwiftUI. |
Beta Was this translation helpful? Give feedback.
Since the "concurrency" update, the easiest way to handle this is indeed an
AsyncSequenceof some sort. The most convenient approach involves 2 actions: one that you can call.observeDependency(or.task) that you use to trigger and handle the subscription's lifecycle, and one that you can call.receivedEvent(Value)that you use to perform the changes when appropriate.In you reducer, you implement:
Now in th…