In re-frame, I have a view that is essentially this:
(defn tool-panel []
(let [current-tool (re-frame/subscribe [:current-tool])]
(fn []
[:h1 (@current-tool "name")])))
It is immediately displayed but current-tool might take a while to appear as unless it was previously loaded, the tool data needs to be requested from the server. During that time, @currrent-tool is nil and this code crashes. What's the appropriate way to deal with this? I thought of doing this:
(defn tool-panel []
(let [current-tool (re-frame/subscribe [:current-tool])]
(fn []
(when @current-tool
[:h1 (@current-tool "name")]))))
which works, but it displays a blank page while loading. If I do:
(defn tool-panel []
(let [current-tool (re-frame/subscribe [:current-tool])]
(fn []
(if @current-tool
[:h1 (@current-tool "name")]
[:h1 "Loading"]))))
I feel that this view is taking an extra role that it should have: know how to display loading messages. Furthermore, I can see this quickly evolving into:
(defn tool-panel []
(let [current-tool (re-frame/subscribe [:current-tool])
foo (re-frame/subscribe [:foo]
bar (re-frame/subscribe [:bar])]
(fn []
(if (and @current-tool @foo @bar)
[:h1 (@current-tool "name")]
[:h1 "Loading"]))))
and that feels like a common pattern that I'll repeat over and over again. Since re-frame is providing a pattern already I'm wondering if I'm missing something. Is there a different way to structure an app that uses re-frame to not end up having to abstract away this pattern that I just found?
I suppose in more generic terms I could say, how do you deal with missing data in reagent apps?
I don't think you are missing too much.
The goal of a Component is to render state, and if that state isn't there yet, then there's nothing to render, except perhaps a message saying "Still loading ...".
There is a Wiki page around this: https://github.com/Day8/re-frame/wiki/Bootstrap-An-Application