The pattern we use is to have our Page.update functions return
(model, cmd, storeCmd)
the main update then applies the storeCmd to the Store. (the actual code
supports a few other things but that's the basic gist of it). Hit me up on
slack if you want to chat about it.
On Sunday, 30 April 2017 08:45:49 UTC+2, Dustin Farris wrote:
>
> I think I've just had an aha moment with this post.
>
> I am in the process of refactoring my monolith MUV into separate modules
> with their own MUV for each "page" of my SPA. Up to this point, I have had
> a separate Store module with its own Model and Msg types and an update
> function (no view, obviously). This has worked well up until now, but
> after splitting off the pages of my app, it is getting more cumbersome to
> update the Store in a way that looks nice.
>
> e.g. in my Main.elm I'm ending up with something like
>
> update msg model =
> case msg of
> UserProfilePageMsg msg_ ->
> let
> ( userProfilePageModel, userProfilePageCmd ) =
> UserProfilePage.update msg_ model.userProfilePage
> in
> case msg_ of
> UserProfilePage.StoreMsg msg__ ->
> let
> ( storeModel, storeCmd ) =
> Store.update msg__ model.store
> in
> { model
> | userProfilePage = userProfilePageModel
> , store = storeModel
> }
> ! [ Cmd.map UserProfilePageMsg
> userProfilePageCmd
> , Cmd.map StoreMsg storeCmd
> ]
> _ ->
> { model | userProfilePage = userProfilePageModel }
> ! [ Cmd.map UserProfilePageMsg
> userProfilePageCmd ]
>
>
> and so on for every page that invokes Store.Msg—which is most pages.
>
> I am thinking that there is a better way, and perhaps Kasey's suggestion
> of forgoing an in-memory Store on the Model might be it. I'm still not
> sure—I do like the snappy feel of a page loading instantly if the data is
> in memory—even if it might change after a brief consultation with the
> server.
>
> Dustin
>
>
> On Wednesday, April 19, 2017 at 7:28:06 PM UTC-4, Kasey Speakman wrote:
>>
>> I'm probably slow, but in recent months I've discovered that trying to
>> use Elm's Model like a database or cache (as I have previously seen
>> suggested) has turned out to be pretty painful for me. An example
>> database-minded model where a section could display *either* a list of
>> employees *or* a list of courses.
>>
>> type alias Model =
>> { employees : List Employee
>> , courses : List Course
>> , loadingError : Maybe Http.Error
>> , route : MyRoute -- employee or course
>> }
>>
>> The problem this runs into is having to worry about state management. I
>> have to remember to "reset" or "turn off" things when they are not active.
>> As my application grew, I had a lot of problems that boiled down to tedious
>> state management details. My cached data didn't turn out to be all that
>> useful because I usually had to reload it anyway, in case something changed.
>>
>> Instead, I have been moving toward the model only representing the
>> current state of my UI. The big difference here is the model representing
>> the current *visual* elements and their data. This leads more to using
>> union types to represent parts of the UI. When you switch to a different
>> case of the union type, the data from the previous case is *dropped on
>> the floor*. This leaves nothing to remember to "reset". RemoteData is a
>> good micro-example of this. If there was an error fetching the data, when
>> the user requests the data again, you switch back to Loading, the error
>> message is dropped on the floor. No forgetting to hide it.
>>
>> type RemoteData e a
>> = NotAsked
>> | Loading
>> | Failure e
>> | Success a
>>
>> If it is really important to cache the data, I prefer to keep that as a
>> persistence concern, not on Model. It can be part of the process for
>> retrieving the data to first check my chosen cache before making a request
>> for fresh data. For instance, first check local storage before making an
>> HTTP call. (Currently, this scenario is easier with Native modules for lack
>> of Local Storage API or being able to wait on port subscriptions. But it's
>> still doable.)
>>
>> So working towards a Model reflecting the visuals on the page has been an
>> interesting challenge. I'm not claiming it's easier, but so far I've found
>> it avoids a class of problems, and has led to some interesting discoveries
>> in my own apps. One small example: I realized that my LoggedIn and
>> NotLoggedIn routes should actually be separate "apps". Attempts to model
>> this in a SPA fashion with the LoggedIn and NotLoggedIn routes as siblings
>> always came up with the conundrum: how do I make it a compiler error for
>> the model to be in LoggedIn mode but I receive a NotLoggedIn message, or
>> vice versa? Even using TEA, I could not avoid this situation. Then I
>> realized the only way to do that would be as separate apps. And that it was
>> entirely possible to separate them. My "login page" turned out to be an
>> entirely self-contained process: the user filling in info, obtaining a
>> token, and saving it to local storage.
>>
>> I post this in the slim hope it is helpful to someone.
>>
>
--
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.