Fork me on GitHub
#helix
<
2020-11-01
>
Christopher Stone16:11:58

Hello, I am trying to use helix to display a leaflet map but am not able to get it to display... it would be handy if the docs showed a few different examples using use-state and use-effect :once to display the initial map... can somebody who knows how to use helix send me a working code example of how to use form 3 components, thanks peeps

lilactown16:11:11

I’m not sure what you mean by a form 3 component?

lilactown16:11:58

If you know the JS you’d write, it’s not hard to do a mechanical translation into helix. I can help with that

Christopher Stone16:11:19

var map = L.map('map', { center: [51.505, -0.09], zoom: 13 });

Christopher Stone16:11:10

thats the code that displays the map, 'map' after the opening brackets represents the html element id it will me displayed in

Christopher Stone16:11:15

I'll send the link to leaflets website it may make more sense to you: https://leafletjs.com/reference-1.7.1.html

lilactown16:11:26

can you show me what you’ve tried so far?

Christopher Stone16:11:36

(defnc customer-map [] (use-effect :once (fn [] (L.map "map" (clj->js {:center default-center :zoom 9 :layers [(L.tileLayer osm-url copy-osm)] })))))

lilactown16:11:02

The use-effect macro wraps everything you pass in after the dependencies (in this case :once) in a function for you

lilactown16:11:44

So right now, the function you’re passing in is being returned by the function that use-effect creates to wrap it, and not running

lilactown16:11:28

Well, it runs on unmount 😅

Christopher Stone16:11:45

I don't understand how it all works...

Christopher Stone16:11:00

Thanks for taking the time to help me by the way

3
lilactown16:11:17

If you remove the function you’re wrapping (L.map ,,,) in it will get you closer

Christopher Stone16:11:01

how will the map be displayed then?

lilactown16:11:49

It will run when the effect gets run

Christopher Stone16:11:28

but I have that code nowhere else

Christopher Stone16:11:55

here is an example I found written in js, using hooks;

Christopher Stone16:11:10

import React from 'react';
import L from 'leaflet';

function Map() {
  React.useEffect(() => {
    // create map
    L.map('map', {
      center: [49.8419, 24.0315],
      zoom: 16,
      layers: [
        L.tileLayer('http://{s}.', {
          attribution:
            '&copy; <a href="">OpenStreetMap</a> contributors'
        }),
      ]
    });
  }, []);


  return <div id="map"></div>
}

export default Map;

Christopher Stone16:11:02

how would I convert that to use helix?

lilactown16:11:03

I mean write it like this:

(defnc customer-map []
  (use-effect
   :once
   (L.map "map" (clj->js {:center default-center
                          :zoom 9
                          :layers [(L.tileLayer osm-url copy-osm)]})))
  ,,,)

lilactown16:11:14

without the (fn [] ,,,) wrapping the body of the effect

lilactown16:11:37

the docs on hooks document the differences between React's useEffect and helix's use-effect: https://cljdoc.org/d/lilactown/helix/0.0.12/doc/hooks#doing-side-effects

lilactown16:11:17

words are hard! and this is a confusing bit of syntactical difference between React and helix. helix's use-effect automatically wraps whatever you pass into it in a (fn [] ,,,), so wrapping it again, isn't doing what you want here

Christopher Stone16:11:24

I tried it both ways, I am going to give it another go now...

lilactown16:11:05

e.g.:

(react/useEffect
  function () {
    console.log("hi");
  }, [])
is the same as
(use-effect
 :once
 (js/console.log "hi"))

lilactown16:11:50

there could be another error, but this way we'll definitely be running that effect on mount

Christopher Stone16:11:12

this is the error I get

Christopher Stone16:11:36

react-dom.development.js:23276 Uncaught #error {:message "Props received were … onent as a function."Props received were a map. This probably means you're calling your component as a function., :data {:props nil}} commitRootImpl @ react-dom.development.js:23276 exports.unstable_runWithPriority @ scheduler.development.js:647 runWithPriority$1 @ react-dom.development.js:11277 commitRoot @ react-dom.development.js:22991 performSyncWorkOnRoot @ react-dom.development.js:22330 scheduleUpdateOnFiber @ react-dom.development.js:21882 updateContainer @ react-dom.development.js:25483 (anonymous) @ react-dom.development.js:26022 unbatchedUpdates @ react-dom.development.js:22432 legacyRenderSubtreeIntoContainer @ react-dom.development.js:26021 exports.render @ react-dom.development.js:26104 reagent$dom$render_comp @ dom.cljs:18 (anonymous) @ dom.cljs:48 (anonymous) @ dom.cljs:38 app$core$start @ core.cljs:82 app$core$init @ core.cljs:94 (anonymous) @ shadow.module.main.append.js:2

Christopher Stone16:11:04

Props received were a map. This probably means you're calling your component as a function.

lilactown16:11:23

it sounds like you might be calling your component like (customer-map {:foo "bar"}) ?

lilactown16:11:03

okay. I see reagent in the stack trace

lilactown16:11:27

how are you trying to render the helix component from reagent?

Christopher Stone16:11:40

as a hicup component

Christopher Stone16:11:23

but I've tried it with and without square brackets and normal brackets

lilactown16:11:37

I can help with that. Before that, though, is there a particular reason you're using reagent and helix together?

Christopher Stone16:11:26

my app is using re-frame so I need reagent

lilactown16:11:11

okay. when you want to render a helix component inside a reagent one, the easiest way to do it is to use helix's $ macro

lilactown16:11:14

e.g.:

(defn app
  [:div
   [:h1 "My App!"]
   [menu options]
   [:div
    ($ customer-map)]])

Christopher Stone16:11:22

excellent, thank you I shall try that now, thank you so much 🙂

Christopher Stone17:11:41

Thank you so much, I have it working now

Christopher Stone17:11:11

Have a great day and keep up the good work

6