TCA Modelling Problem: One-To-Many Global Action To Local Reducers

I have a modelling problem with the current TCA based app I'm working on.
In the app there are many modules with associated local actions and states.
However, there are also global actions which need to be handled by several of the modules.

To give a concrete example, a BLE peripheral is publishing .data([UInt8]), .connect or .disconnect App.Action to the store. Many modules need to handle these same actions (but the handling is module specific).

How should a common global action type be handled by modules which only operate on local action types?

Any help would be most appreciated - I've been thinking about this for a while now, but all workarounds I can think of have their own issues.

I would go for a single BLEState/BLEAction/bleReducer set that I would pullback to separate modules under bleState property and bleAction(_:) action.

1 Like

Hi - thanks for the idea. I'm not sure how it would work though - say there is a common action e.g. BLEAction which is driven / published by a BLE peripheral. The App's Store must subscribe to this BLEAction - so let's say we model it something like this:

enum AppAction
{
   case ble(BLEAction)
   case someModuleA(SomeModuleAAction)
   case someModuleB(SomeModuleBAction)
}

both SomeModuleA and SomeModuleB must handle the BLEAction, so we could model their Actions as:

enum SomeModuleAAction
{
   case ble(BLEAction)
}

enum SomeModuleBAction
{
   case ble(BLEAction)
}

We can pullback SomeModuleA and SubModuleB reducers to an App reducer, but the BLEAction is common across sub modules, so it needs to be published as an AppAction. It feels like the opposite of a pullback is needed - e.g. the BLEAction needs to be extracted from the AppAction and embedded into the relevant SubModule Action type.

One idea I had is to have an App reducer for BLEActions which switches on the current AppState, and maps the BLEAction to the relevant SubModule Action type (returning a SubModule Action as a side-effect) depending on the AppState.
e.g. if an AppAction.ble is received, and the AppState is .someModuleA, then the reducer would return a side-effect of SomeModuleAAction.ble.

It will produce a fair amount of boiler plate - but is easy to understand. Any thoughts?

Do you really need to handle BLE actions in AppState? I thought you could handle BLE actions only in different modules separately. If you pulled back BLEreducer it would trigger changes in different reducers that are pulled back into state.

1 Like

I'm not sure I understand your idea @eimantas:

I thought you could handle BLE actions only in different modules separately. If you pulled back BLEreducer it would trigger changes in different reducers that are pulled back into state.

Do you mean in addition to:

Reducer<SomeModuleAState, SomeModuleAAction, SomeModuleAEnvironment>

you could have e.g.

Reducer<SomeModuleAState, BLEAction, SomeModuleAEnvironment>

Requiring both to be pulled back to the global Action and State used by the app's Store?

That sounds like it would work - I'm not sure what it means for modularity (and particularly module testing), because mutations to e.g. SomeModuleAState would depend on several reducers.

I hate to ask because I know you're incredibly busy, but was wondering if you have any suggestions please @stephencelis?