I've got this series of events and effects to interact with the Google Maps API:
(reg-event-db
:config/save-map
(fn [db [_ map]]
(assoc db :config.geo/map map)))
(reg-event-db
:map/update-map
(fn [db [_ canvas lat-lng]]
(let [Map (get db :config.geo/map)]
(assoc db :map/current-view (Map. canvas (clj->js lat-lng))))))
(reg-event-fx
:maps/set-current-center
(fn [{:keys [db]} [_ new-center]]
(let [new-coords (get-in db [:config.maps/coords new-center])]
{:fx [[:dispatch [:map/update-map (gdom/getElement "map-canvas")
{:center new-coords
:zoom 13}]]]})))
(reg-event-fx
:config/load-google-maps
(fn [_ _]
{:google-maps nil}))
(reg-fx
:google-maps
(fn [_]
(js-await [_ (try (.load (Loader. #js {:apiKey api-key
:version "weekly"}))
(catch js/Error e
(throw (ex-info "failed to load JS Maps API" {:cause e}))))]
(js-await [lib (js/google.maps.importLibrary "maps")]
(dispatch [:config/save-map (gobj/get lib "Map")])))))
On various screens throughout my app, I am constructing a new map and rendering it. But if I want to see the change I expect, I have to click twice on a route before the change to the map takes. I'm guessing there's a bug in my code but I'd appreciate some insight. Should I perhaps instead just use the mutability provided by the Map class and update its state that way?One potential issue is that, it seems, (Map. canvas ...) actually mutates that canvas. And event handlers should be pure.
Another potential issue might be in the way :map/current-view is used, if it is used.
Yet another potential issue is re-using the same canvas for different maps.
Finally, mutating an existing map object is always better than creating a completely new one each time you need to do something since that's how it was designed.
Unrelated comments:
• With React, you seldom need to access DOM elements by ID. That (gdom/getElement "map-canvas") should probably become a ref
• (gobj/get lib "Map") can be (.-Map lib)
yeah, I am a little suspect about the :map/current-view myself. It doesn't do anything, yet, except hold that map state. I did attempt to use Map.setCenter to update the existing map but it didn't change anything about that double-click scenario. I'm gonna explore the ref solution.