Open AlexeyRaga opened 8 years ago
The assumption right now is that only one component will handle any action. There is no routing, since the callback you get really just updates the state of the React component.
Maybe the solution is to add some way to getState
as well.
This seems to work in my simple example:newState < T.cotransform id
but I have no idea if this is the correct approach.
listActions :: T.Spec _ State _ Action
listActions = T.simpleSpec performAction T.defaultRender
where
performAction :: T.PerformAction _ State _ Action
performAction (ItemAction i Increment) _ oldState = do
newState <- T.cotransform id
lift $ liftEff $ log $ "newState: " <> (show newState) <> " oldState: " <> (show oldState)
pure unit
performAction _ _ _ = pure unit
I am not sure about the exact order in which the cotransforms will be applied (can this even be guaranteed, if there is an async action in the child for example ?).
One of the use cases where I feel I need this feature, are form components ( each field is a separate component, when the entire form is filled out, additional async validation needs to be performed)
Thank you!
To answer one of my questions: I've added delays from counter example in the child component:
delay :: Int -> Aff _ Unit
delay ms = later' ms (pure unit)
making it async, so the parent's action will be called after the child's action has finished
@kozak We had the exact same issue.
delay
is approximate solution and if there is any ajax call involved we will not be able to guarantee that parent's action will be called after the child's action.
The best way is to use the Prism
to avoid sending that particular call to the child and handle that particular action in the parent itself, using pattern matching over the child's action!
Child.purs
data Action
= Increment
| Decrement
| HandleInParent
Parent.purs
data Action
= MyAction
| ChildAction Child.Action
performAction (ChildAction HandleInParent) _ _ =
<do stuff>
performAction (ChildAction _ ) _ _ =
pure unit
Prism example... the following is not related to the above code... just an example to show how to avoid a particular action from reaching the child spec!
_TaskAction :: Prism' TaskListAction (Tuple Int TaskAction)
_TaskAction = prism (uncurry TaskAction) \ta ->
case ta of
TaskAction i HandleInParent -> Left ta
TaskAction i a -> Right (Tuple i a)
_ -> Left ta
@paf31 What do you think about this idea? too complex/confusing? can it be simplified?
@sudhirvkumar If I remember correctly (it has been a while) what I meant by saying that I've added delay
is that I've added them to check the async behaviour of child vs parent (not as a workaround, but to check the resulting order of performAction calls in presence of async cotransforms).
The result was that even with async action the parent performAction
is called after the child has finished.
That said, what you suggest seems to be in agreement with Paf's statement:
The assumption right now is that only one component will handle any action
and is also intuitive ;)
@kozak Thanks for your quick reply. Do you have any suggestions to improve the code example? or what I have is good enough?
I am not experienced enough to be able to help you here - but you could probably just ignore the actions you are not interested in (in the child):
performAction _ _ _ = pure unit
Have a look at lines 75-79 : http://try.purescript.org/?gist=f5f273e4c5e4161fceff&backend=thermite
Hi,
I am using the following lens-based approach to propagate a part of the state to the downstream components:
The first component renders a list of items, the second doesn't render anything but defines
performAction
.When
listItemSpec
is updating the state the change is correctly propagated to the parent component through the lens, but theperformAction
in the second component (listActions
) always receives the "old" state, the one "before" changes are applied through the_items
lense.How can a parent component update the state after it has been altered by its children?
Thanks.