-
Let's say we are building a search UI, and would like to throttle search requests. We would have an action to represent the user changed the text field, and a new search request effect can be initiated there. How would we throttle it? I have three ideas in mind: The first is just putting throttling management state as part of the feature state. I haven't went it the details of this approach, but it certainly feels redundant, error-prone, and obfuscating the core logic of the feature. Creating an coordinator object from the search client and storing the object in our state. We can hold an I chose this approach, but just by writing the above done I already feel like this is tricky to get right. For instance, older search requests can return later than more recent ones, leading to outdated results. The primary concern I had over this one is that storing an object in the state feels extremely wrong. I can probably get over this during testing since we are doing patch-style equality check, but something just feels wrong. Moving the job to the client. Maybe there we can use an search caller id and do throttling using id. If globally the app will only use this search functionality once, we can even get rid of this. It does feel the reverse of the first approach though, making reusing logic a little bit difficult. And technically throttling is a part of the UI, not the backend. Do you people have any suggestions, or sharing some light into what you did in similar situations? Thanks |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 6 replies
-
Have a look here : https://github.com/pointfreeco/swift-composable-architecture/blob/main/Examples/Search/Search/SearchView.swift Easy and testable, not much management to be done in state |
Beta Was this translation helpful? Give feedback.
-
As @Alex293 mentioned, the Search demo app shows how to debounce text field changes in order to perform a network request. It does so in the easiest way, which is to defer the debouncing logic to the Alternatively you can debounce actions going into a reducer via a pattern like this: case let .textFieldChanged(text):
state.text = text
return .run { send in
enum CancelID { case debounce }
try await withTaskCancellationHandler(id: CancelID.debounce) {
try await Task.sleep(for: .milliseconds(300))
// API request...
}
} |
Beta Was this translation helpful? Give feedback.
Have a look here : https://github.com/pointfreeco/swift-composable-architecture/blob/main/Examples/Search/Search/SearchView.swift
Easy and testable, not much management to be done in state