Fork me on GitHub

Hello everyone. I have a view in a SPA that needs to refresh data from a server every 5 seconds. I wonder how to implement it in re-frame


can someone point me to the right direction please?


Great! Thank you very much

👍 1

hey! is there any development on this issue? i am looking for a good method to attach docstrings to events, effects, subscriptions, ideally with ability to export some open doc format,


If there were, they would've been in the issue.


At least, that's usually the case.


I've gotten to a stopping point with my re-frame app. I'm pretty happy with the code size of the application, and not too unhappy with the code, the main issue being the somewhat clunky navigation. I wonder if the (relatively low-level) re-frame framework is the best way to go, rather than using a route-based framework such as keechma or kee-frame. Has anyone used these frameworks and, if so, are willing to offer advice based on their experience?


I have no experience with keechma, but I definitely wouldn't call kee-frame a "framework". It's just a set of convenient functionalities on top of re-frame, mainly its controllers tied to route changes. It's definitely a nice thing to have on top of re-frame.


@U0DTU8J83 Obviously re-frame doesn't officially prescribe routing; you've got many options from various libraries, templates or layers on top. In my opinion the most elegant and sophisticated example I've seen of routing on top of re-frame is the frontend which was written by Pedro Girardi (ex JUXT). Its not just the routing, he has thought of a very elegant stack-based data model underlying his router that gives it a lot of superpowers.


Thanks to both for your advice. I'll have a look at x convex-web and look more at kee-frame.

Vincent T19:03:33

I know this is an old thread, but holy cow that router src was an inspirational read! Thanks @U0G75S29H


So, I've been trying to integrate a javascript graph layout library into my app (elkjs in case it matters). Essentially my app-db has a map that needs to get fed into the graph layout algorithm, which will return a new JSON object with the diagram layout (which I then translate into positioning in an SVG). The sticking point is that it returns it as a promise, and I can't quite wrap my head around how to put the result of a promise into the hiccup layout data structure for re-frame. When I've used re-frame in the past I haven't previously had to deal with calling out to a js library that uses async promises, so I'm a bit lost. I gather the preferred way is to write an effect that updates the graph layout when the underlying data changes? Are there any best practices for this? I've searched and found some stuff, but what I've found so far seems a bit inconclusive, or not quite the same situation.


Remove re-frame from the equation for a moment. Just write a Reagent component that accepts some CLJS data and does everything you need (assuming, there's no complex state that you'd like to preserve or some IO in there). And then use that Reagent component from the comfort of re-frame.


That makes sense. I'll try it!



  (fn [{:keys [graph on-success on-failure]}]
      (let [js-elk (ELK. #js {"workerFactory" (fn [url] (Worker. url))})]
        (-> (ocall js-elk :layout (clj->js graph))
            (p/then (fn [js-result]
                      (dispatch (conj on-success (js->clj js-result :keywordize-keys true)))))
            (p/catch (fn [error]
                       (dispatch (conj on-failure {:error error})))))))))


@U0CJXQ13N Requires using shadow-cljs:

[oops.core                     :refer [oget oset! ocall oapply ocall! oapply!
                                           oget+ oset!+ ocall+ oapply+ ocall!+ oapply!+]]
[promesa.core                  :as p]
["elkjs/lib/elk-api"           :default ELK]
["elkjs/lib/elk-worker.js"     :refer (Worker)]


thanks! I'll have to study these to make sure I understand what they're doing, but using promesa makes sense.


Neither propmesa nor cljs-oops are necessary above - the amount of lines of code will be the same. And by using just interop, the amount of character will actually be less. :)


Hi, I'm following along but am struggling to do the same (similar?). (Let me know if i should post a new thread, still trying to understand slack etiquette) . Mine is a bit of a pain to deal with (and debug), as i'm trying to bundle it into a chrome extension. It's retrieving promises from a content.js message via chrome messaging, and I need to somehow get that promise into my app-db. (The details are it's grabbing the selected text when clicking on the extension popup...) I guess i'm a bit confused on if the selectionPromise is actually returned... and if it's deref'd or something? I don't understand javascript very well and any tips appreciated.

 (fn [{:keys [graph on-success on-failure]}]
   (let [-process-response (fn [response]
                             (let [aget-response-st (aget response "st")]
                               ;; NOTE This seems to work:
                               (js/alert (str "received message:" aget-response-st))
                               (js/console.log (str "recieved message:\n" aget-response-st))
                               ;;   TODO Dispatch... how?
         -send-message (fn [tabs]
                         (let [tab-id (.. (aget tabs 0) -id)]
                           (js/console.log "tab id:\n" tab-id)
                           (.. js/chrome -tabs (sendMessage tab-id
                                                            (clj->js {:command "requestSelection"})
         selection-promise (.. js/chrome -tabs (query (clj->js {"active" true
                                                                "currentWindow" true})
     (-> (ocall selection-promise :page-selection (clj->js graph))
         (p/then (fn [js-result]
                   (dispatch (conj on-success (js->clj js-result :keywordize-keys true)))))
         (p/catch (fn [error]
                    (dispatch (conj on-failure {:error error}))))))))


I'm getting this as an error, I don't even see where i'm looking to eval a string at this point. EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'".


ok, for any future readers, this seems to work for me. Huge PIA to debug without a repl (as a chrome extension, chromex isn't an option as i need manifest v3)

(rf/reg-event-db ::save-selection
                 (fn [db [_ selection ]]
                   (assoc db :search-form selection)))

(defn ^:dev/after-load mount-root []
  (let [root-el (.getElementById js/document "app")
        ;; NOTE This is gross?
        _ (.. js/chrome -tabs (query (clj->js {"active" true
                                               "currentWindow" true})
                                     (fn [tabs]
                                       (.. js/chrome -tabs (sendMessage (.. (aget tabs 0 ) -id)
                                                                        (clj->js {:command "requestSelection"})
                                                                        (fn [response]
                                                                          (dispatch [::save-selection (aget response "st")])
                                                                          (js/console.log "Got selection: \n" (aget response "st"))))))))
    (rdom/unmount-component-at-node root-el)
    (rdom/render [dispatch-panel] root-el)))