-
-
Save jhchabran/e09883c3bc1b703a224d to your computer and use it in GitHub Desktop.
| ; Following code is WRONG, see comments for details. | |
| (defn google-map [] | |
| (let [pos (subscribe [:current-position])] | |
| (reagent/create-class | |
| {:reagent-render | |
| (fn [] | |
| [:div | |
| [:h4 "Map"] | |
| [:div#map-canvas {:style {:height "400px"}}]]) | |
| :component-did-mount | |
| (fn [] | |
| (let [map-canvas (.getElementById js/document "map-canvas") | |
| map-options (clj->js {"zoom" 9}) | |
| gmap (js/google.maps.Map. map-canvas map-options) | |
| marker (js/google.maps.Marker. (clj->js {:map gmap :title "Drone"}))] | |
| (reagent.ratom/run! | |
| (let [latlng (js/google.maps.LatLng. (:latitude @pos) (:longitude @pos))] | |
| (.setPosition marker latlng) | |
| (.panTo gmap latlng)))))}))) | |
| ; Another attempt, using props and lifecycle to udpate marker position | |
| (defn gmap-component [] | |
| (let [gmap (atom nil) | |
| options (clj->js {"zoom" 9}) | |
| update (fn [comp] | |
| (let [{:keys [latitude longitude]} (reagent/props comp) | |
| latlng (js/google.maps.LatLng. latitude longitude)] | |
| (.setPosition (:marker @gmap) latlng) | |
| (.panTo (:map @gmap) latlng)))] | |
| (reagent/create-class | |
| {:reagent-render (fn [] | |
| [:div | |
| [:h4 "Map"] | |
| [:div#map-canvas {:style {:height "400px"}}]]) | |
| :component-did-mount (fn [comp] | |
| (let [canvas (.getElementById js/document "map-canvas") | |
| gm (js/google.maps.Map. canvas options) | |
| marker (js/google.maps.Marker. (clj->js {:map gm :title "Drone"}))] | |
| (reset! gmap {:map gm :marker marker})) | |
| (update comp)) | |
| :component-did-update update | |
| :display-name "gmap-component"}))) | |
| (defn gmap-wrapper [] | |
| (let [pos (subscribe [:current-position])] | |
| (fn [] | |
| [gmap-component @pos]))) |
So far and according the feedback I got, 2 and 3 are correct. 4is probably correct anyway. Still waiting for some validations on 1 :)
I feel like if's correct enough it would be a nice addition to https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/google-maps given the re-frame part is replaced with a ratom.
4 was just a consequence of putting the run! at the wrong place, initial comment updated accordingly.
I don't think it was wrong per se but it's now unnecessary once run! is called where it should be.
run! is very wrong here (if following re-frame approach).
Discussion here: https://clojurians-log.clojureverse.org/reagent/2015-08-05.html
I rewrote it, see https://gist.github.com/jhchabran/e09883c3bc1b703a224d#file-2_google_map-cljs if you're interested :)
It should use will-receive-props for update as we don't interact with the dom as opposed to http://nils-blum-oeste.net/clojurescripts-reagent-using-props-in-lifecycle-hooks/ example.
When using this I have found it important to run :component-will-unmount to dispose of the stateful component
While it's working (at least appears to be, I get my map panning properly according to gps position), I'm asking myself the following questions : ( 1 being the one I'm the most unsure of, to 4 being where I think I got it right).
reagent.ratom/run!, isn't it a clear violation of one the re-frame's principles, which states, do not usereactionin views ? (run!being, as far as I understand, a reaction that runs itself initially whereas reaction requires to be deref'ed to be executed, but in this case, it doesn't hold any meaningful value).setPositionin the:reagent-renderfunction works but it felt wrong because the markup once rendered doesn't change at all.letinside a letletbut while being usually a hint of something done wrong, puttinglatlngthere doesn't work because it's not dereferenced in the render function, so it seems fine to me.storing the google map instance inJust added it to the let block as theapp-dbfeels wrong to me, I thought it's more something related to the component that the app state itself. Still I need to hold a reference to it to be able to update the map according toapp-db, so a local atom felt right. see previous revisionrun!is now called inside:component-did-mount.