I am struggling to understand how to handle very temporary state. For a very simple example, lets say you have a view that displays a list of favorite Numbers. Your appState would look something like this
struct AppState {
var favorateNumbers: [Int]
}
Now lets say there is a button on this view that displays a list of all numbers (or a finite list) and the app allows you to pick as many as you want to add to your favorites. But to finalize your selections, there is a save button. This model would look something like this
var allNumbers: [Int]
var selectedNumbers: [Int]
}
enum NumbersAction {
case select(Int)
case save
}
let reducer: Reducer<NumbersState, NumbersAction, Void> = Reducer { state, action, _ in
switch action {
case .select(let number):
state.selectedNumbers.append(number)
return .none
case .save:
////Here is the problem
}
The only way currently to implement the save
case is to have AppState
hold on to the temporary selected numbers.
struct AppState {
var favorateNumbers: [Int]
var temporarySelectedNumbers: [Int]
}
This may be fine for very small apps, but I work on a large app, where this scenario is produced multiple times. This 'temporary' state will litter my State
structs.
Does anyone have an idea on how to remove this type of temporary state? My thought is to add a reduce
function higher-order Reducer
.
extension Reducer {
public static func reduce<PrivateState>(
_ privateState: PrivateState,
reducer: @escaping (inout PrivateState, inout State, Action, Environment) -> (PrivateState, Effect<Action, Never>)
) -> Reducer {
var privateState = privateState
return Reducer { state, action, environment in
let (newState, effect) = reducer(&privateState, &state, action, environment)
defer { privateState = newState }
return effect
}
}
}
I am not a big fan of the name, I think it could be confusing, but I believe this reducer would allow one to remove very temporary state from their architecture
struct AppState {
var favorateNumbers: [Int]
}
enum Action {
case add(Int)
case save
}
let reducer = Reducer.reduce([Int](), reducer: { selected, state, action, _ in
var temp = selected
switch action {
case .add(let number):
temp.append(number)
case .save:
state.numbers = temp
}
return (temp, .none)
})