Brilliant! Thanks a lot!
To summarise what I understood:
- A component should only update its internal states
- All updates of shared states should be done at a higher level
which could be further summarised in:
A state should only be updated by its owner (i.e. the highest component
where that state appears) & no state should appear twice in the component
chain.
There's just a slight glitch in your previous answer: WaypointConf is *not*
100% synchronised: it needs its internal update to handle its hover state
(for example, when hovering on a waypoint date date a button appears to
open the corresponding date picker to modify it & the date picker has its
own internal state such as hovering, open/closed etc.)
So while I do agree the slider can be reduced to a view, I don't think the
WaypointConf can, which in turn means the Profile can't either.
Things get nasty when you try to synchronise shared states with internal
ones, so don't do it (which, I think, is what you meant in a previous post
with options 1 & 2).
A component can only operate on two kinds of states:
- states other components need to know: those are managed by a component
higher up
- states others don't need to know: they should not depend on the previous
ones & are managed by an internal update.
Am I on the path to enlightenment?
On Thursday, August 25, 2016 at 6:04:32 PM UTC+2, Richard Feldman wrote:
>
> Thanks! So let's start by talking about Slider for a sec.
>
> SliderMsg (Slider.ChangeValue newSpeed) ->
> { model | profile = newInternal, shared = Trip.setAverageSpeed
> model.shared newSpeed }
>
> Because this code compiles, and it only covers the ChangeValue
> constructor, then assuming speed is an Int, I can infer that Slider's Msg
> looks like this:
>
> type Msg = ChangeValue Int
>
> A good question at this point is: *how much of Slider's state must be
> synchronized *with other state in the application?
>
> For example, if Slider had some sort of visual flourish like "every time
> you drag it, it changes color," that state would not need any
> synchronization with other parts of the app. The slider would change color
> when you dragged it, and the rest of the application would neither know nor
> care.
>
> The Slider's value is not independent like this. If you put a slider on a
> page and its value changes, but no other code ever finds out that its value
> changed, then the slider is useless! Its value needs to be synchronized
> with other state in order to be useful.
>
> Since Slider has no other state besides this value, then Slider's state is
> *100%
> synchronized* with other state. In a case like this, you have two options
> for keeping it in synchronized:
>
> 1. Give Slider its own Msg, and translate between its Msg and its caller's
> Msg
> 2. Do not give Slider its own Msg, just have its view accept a Msg
> *constructor* as an argument.
>
> The second option is simpler. Here's how that would look:
>
>
> viewSlider : (value -> msg) -> value -> Html msg
>
>
> Now we can change Profile's Msg to this:
>
> type Msg =
> WaypointConfMsg Int WaypointConf.Msg
> | *SetSpeed Int*
>
>
> ...and render the slider like this:
>
> viewSlider SetSpeed currentSpeed
>
> So now Slider no longer has its own Msg, it just says "hey caller, tell me
> how to wrap my values in your Msg type, whatever that might be, and we're
> cool." Now instead of Slider being a Model, a Msg, an update, and a
> view...it's just a view! :)
>
> Let's look at Waypoint next:
>
> WaypointConfMsg idx msg' ->
> case msg' of
> WaypointConf.ChangeDateOrTime _ ->
> { model | profile = newInternal, shared = Trip.changeOpDate
> model.shared idx <| getDate idx model newInternal }
> WaypointConf.SameDateAndTime _ ->
> { model | profile = newInternal }
>
> Like Slider, its state is still *100% synchronized*, meaning it also
> doesn't need its own Msg. We can convert Waypoint into a view function
> (which accepts a "here's how to wrap things as a Msg" function just like
> Slider did—or maybe two of those functions, since there are two things
> Waypoint can change), at which point we no longer need a Waypoint Msg,
> Model, or update. Only a view.
>
> Finally, since Profile only has Waypoint and Slider inside it, and since
> Profile has no independent state to track either, we can give it exactly
> the same treatment as what we did for Waypoint and Slider.
>
> To summarize how I'd recommend organizing things:
>
>
> *Current*
>
> WaypointConf - Model, Msg, update, view
> Slider - Model, Msg, update, view
>
> Profile - Model, Msg, update, view
>
> App - Model, Msg, update, view
>
>
> *Proposed*
>
> WaypointConf - view
> Slider - view
> Profile - view
>
> App - Model, Msg, update, view
>
>
> Hope that helps! :)
>
--
You received this message because you are subscribed to the Google Groups "Elm
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.