Denis Fuenzalida
Denis Fuenzalida

Reputation: 3346

Fn does not update the DOM, except when called from a browser-attached REPL

I'm porting a TODO app from vanilla JavaScript into ClojureScript. So far so good, except for this innocent looking function:

;; loop the @todo-list, write each todo at the end of the <body>
(defn show-todos []
  (js/alert "in show-todos")
  (map
   #(appendChild (.-body js/document) (.createTextNode js/document (str %)))
   @todo-list))

Another function executes and it calls show-todos and the browser shows the alert message, but nothing updates on the document. However, if I open another terminal and launch a browser-attached repl:

$ lein trampoline cljsbuild repl-listen
Running ClojureScript REPL, listening on port 9000.
"Type: " :cljs/quit " to quit"
ClojureScript:cljs.user> (in-ns 'todo-cljs.todos)
ClojureScript:todo-cljs.todos> (show-todos)
(#<[object Text]>)

This actually DOES adds the contents of the todo-list on the screen. I'm using the lein-cljsbuild plugin version 0.3.0. and only whitespace optimizations.

Any tips?

Upvotes: 0

Views: 66

Answers (1)

Denis Fuenzalida
Denis Fuenzalida

Reputation: 3346

Got a quick answer on the ClojureScript Google group:

The issue was that map is lazy, from the docs:

Returns a lazy sequence consisting of the result of applying...

Using the repl forces the evaluation of the map over the collection (@todo-list). Suggested fixes:

  • Change the call from (map fn coll) to (doseq coll fn)
  • (doall (map... - if you want the results of the map
  • (dorun (map... - if you dont

In my case, dorun did perfectly fine.

Upvotes: 1

Related Questions