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.

Reply via email to