Skip to content

Commit

Permalink
[AnyReducer] - Implement Flag to raise runTimeWarn on Pullback (#102)
Browse files Browse the repository at this point in the history
* implement runWarn using flag

* update flag to assertOnInvalidAction
  • Loading branch information
dikasetiadi authored Oct 19, 2023
1 parent e7bed17 commit 5c9fff0
Showing 1 changed file with 40 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,19 @@ public struct AnyReducer<State, Action, Environment> {
.map(toLocalAction.embed)
}
}


///
/// - Parameters:
/// - toLocalState: A key path that can get/set `State` inside `ParentState`.
/// - toLocalAction: A case path that can extract/embed `Action` from `ParentAction`.
/// - toLocalEnvironment: A function that transforms `ParentEnvironment` into `Environment`.
/// - assertOnInvalidAction: A flag indicate we run assertion for `invalid action` that `not match` with our current extract-ed/embed-ed `State` from `ParentState`.
/// - Returns: A reducer that works on `ParentState`, `ParentAction`, `ParentEnvironment`.
public func pullback<GlobalState, GlobalAction, GlobalEnvironment, StatePath, ActionPath>(
state toLocalState: StatePath,
action toLocalAction: ActionPath,
environment toLocalEnvironment: @escaping (GlobalEnvironment) -> Environment,
assertOnInvalidAction: Bool = true,
file: StaticString = #file,
fileID: StaticString = #fileID,
line: UInt = #line
Expand All @@ -258,32 +266,37 @@ public struct AnyReducer<State, Action, Environment> {
guard let localAction = toLocalAction.extract(from: globalAction) else { return .none }

guard var localState = toLocalState.extract(from: globalState) else {
runtimeWarn(
"""
A reducer pulled back from "\(fileID):\(line)" received an action when child state was \
unavailable. …
Action:
\(debugCaseOutput(localAction))
This is generally considered an application logic error, and can happen for a few \
reasons:
• The reducer for a particular case of state was combined with or run from another \
reducer that set "\(typeName(GlobalState.self))" to another case before the reducer ran. \
Combine or run case-specific reducers before reducers that may set their state to \
another case. This ensures that case-specific reducers can handle their actions while \
their state is available.
• An in-flight effect emitted this action when state was unavailable. While it may be \
perfectly reasonable to ignore this action, you may want to cancel the associated \
effect before state is set to another case, especially if it is a long-living effect.
• This action was sent to the store while state was another case. Make sure that \
actions for this reducer can only be sent to a view store when state is non-"nil". \
In SwiftUI applications, use "SwitchStore".
"""
)
#if DEBUG
if assertOnInvalidAction {
runtimeWarn(
"""
A reducer pulled back from "\(fileID):\(line)" received an action when child state was \
unavailable. …
Action:
\(debugCaseOutput(localAction))
This is generally considered an application logic error, and can happen for a few \
reasons:
• The reducer for a particular case of state was combined with or run from another \
reducer that set "\(typeName(GlobalState.self))" to another case before the reducer ran. \
Combine or run case-specific reducers before reducers that may set their state to \
another case. This ensures that case-specific reducers can handle their actions while \
their state is available.
• An in-flight effect emitted this action when state was unavailable. While it may be \
perfectly reasonable to ignore this action, you may want to cancel the associated \
effect before state is set to another case, especially if it is a long-living effect.
• This action was sent to the store while state was another case. Make sure that \
actions for this reducer can only be sent to a view store when state is non-"nil". \
In SwiftUI applications, use "SwitchStore".
"""
)
}
#endif

return .none
}

Expand Down

0 comments on commit 5c9fff0

Please sign in to comment.