Calling child behaviour from parent (from TCA 1.25 onwards) #3895
Replies: 1 comment
-
TCA2 will have quite a few new features that allow for better child-to-parent and parent-to-child communication. What you are asking for in particular is parent-to-child, and one tool we will be shipping is called "triggers". This lets a child feature hold onto an object that can be "triggered" from the outside, and when triggered it will execute logic in your child feature. As an example, suppose a child feature has the need to refresh data, which can be done with the feature first appears or when a button is tapped, but also you want the ability for a parent to tell the child to refresh. The child can represent this like so: @Feature struct Child {
struct State {
@Trigger var refresh
// Other properties
}
…
var body: some Feature {
Update { state, action in
switch action {
case .refreshButtonTapped:
state.refresh()
}
}
.onMount { state in
state.refresh()
}
.onChange(of: store.refresh) { _, state in
// Do work to refresh state
}
}
}Here we are showing off triggers in 3 ways:
So internally the child feature can "trigger" But the parent feature can do the same: @Feature struct Parent {
struct State {
var child = Child.State()
}
…
var body: some Feature {
Update { state, action in
switch action {
case .tap:
state.child.refresh()
…
}
}
}
}So at any point the parent feature needs to tell the child to do its work it can just hit await store.send(.tap) {
// Assert on all state changes from 'Parent' as well as all
// states changes from 'Child.onChange'
}Everything is still in flight for TCA2 at this moment, so things may change a bit, but so far this is a tool we were able to build and seems like it solves the problem nicely. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
This is effectively a follow-on from the previously answered (but now outdated) discussion here #1952.
I wanted to start the discussion to see what exposing child behaviour to parent features looks like now and in the future.
The previous advice was that sending a child action from a parent reducer as a means of sharing behaviour (i.e. using actions like a function call) was an anti-pattern and could also have performance implications. There were generally two approaches you could take instead:
I believe the performance implications are less of a concern these days but my personal opinion is using actions in this way still feels wrong...
Opinions aside, as of 1.25, the above approaches are deprecated and will not even be possible in TCA2:
.reduceis deprecated, which rules out the second approach above..mapon the returned child effect in order to map its child actions back to a parent action on the parent reducer. This is also deprecated and won't be possible in future.There remains two options if you need either a state mutation or just a re-usable effect:
However as far as I can tell, the only option if you need to have both to happen together is either:
As I'm working through the deprecations in our app I'm left with the view that sending a child action from the parent is now the only really viable solution to this problem. I'm curious if anyone else can think of a better way, or if there might be a better way to handle this in TCA 2.
Beta Was this translation helpful? Give feedback.
All reactions