A minimalistic ClojureScript interface to React.js
Schpaa 2021-05-01T14:37:38.211700Z

Say I want to scroll to an element after a page is rendered. How do I do this? I am using re-frame too. I’ve come to understand that the #element-anchor tag does not work. What I need to do is pick out the # element the router provides me, but here I’m stumped; when is it ok to call (.scrollTo …) or similar when rendering the page??

p-himik 2021-05-01T14:41:54.211800Z

The anchors work, but only within a page that has already been rendered. I usually don't think too hard about it: - Turn a component that has an anchor into a form-3 component - In the :component-did-mount, check the URL if it has its fragment equal to that anchor - If yes, scroll to the element It won't work exactly like it works for plain HTML pages (e.g. if your component re-mounts, then the page will be scrolled again), but you can fix it if needed.

Schpaa 2021-05-01T14:44:22.212Z

ok, do I need to remove the anchor afterwards?

Schpaa 2021-05-01T14:45:51.212200Z

I’ll guess I’ll figure that out myself, thanks for the input!!


Here’s an alternative you might consider:

  (fn [_ _]
    (r/after-render #(when-let [el (first (dom/by-class "error"))]
                       (.scrollIntoView el)))

Schpaa 2021-05-01T14:48:14.212700Z


p-himik 2021-05-01T14:50:30.212900Z

A few things: - The snippet above assumes using re-frame, but this is #reagent - probably, it could be replaced with just r/after-render somewhere, not sure - The event handler in impure, which is discouraged. But the code can be moved to an effect handler. - The code checks for some predefined class - it has nothing to do with anchors

Schpaa 2021-05-01T14:51:13.213100Z

right, but I never seen the r/after-render used before

Schpaa 2021-05-01T15:12:03.213800Z

This worked out just fine, using a form-3 component


All valid points! I just thought it might lead to a solution that’s a little lighter-weight than a form-3 component.

william 2021-05-01T16:36:20.215100Z

where's the documentation for the current method of using react libraries from reagent (with shadow-cljs)?

p-himik 2021-05-01T16:41:01.215200Z

On importing stuff - shadow-cljs documentation. On using React components from within Reagent - Reagent documentation. Lots and lots of relevant documents, articles, and examples, the most relevant ones are right in the Reagent repo.

william 2021-05-01T17:03:48.218900Z

a more specific question on the integration of as a react component from my reagent application: since I'm using shadow-cljs, I installed the dependency via npm install react-cytoscapejs, and I'm importing and try to use it via:

(ns minimal.ui
   ["react-cytoscapejs" :as rcyto :default CytoscapeComponent])

(defn home-page []
   [:> CytoscapeComponent {:elements {:data {:id 1}}}]])
This gives me a lot of errors in the console. I suspect that's because I'm not faithfully translating the example at the end of Do I have to wrap the react component in a component of my own?

p-himik 2021-05-01T17:04:51.219200Z

What is the very first error?

william 2021-05-01T17:05:31.219400Z

module$node_modules$react$cjs$react_development.js:5 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `minimal.ui.home_page`.
    in minimal.ui.home_page

p-himik 2021-05-01T17:06:17.219600Z

It's the :require section then, most likely. Check out this part:

william 2021-05-01T17:07:54.219800Z

I get the same error with:

(ns minimal.ui
   ["react-cytoscapejs" :as rcyto])
(defn home-page []
   [:> rcyto/CytoscapeComponent {:elements {:data {:id 1}}}]])
is this what you had in mind?

p-himik 2021-05-01T17:08:31.220Z

Just do (js/console.log rcyto) at the top level and see what it outputs, proceed from there.

william 2021-05-01T17:10:37.220200Z

I get an object that seems the right one

p-himik 2021-05-01T17:11:54.220400Z

And (js/console.log rcyto/CytoscapeComponent) outputs the component itself?

william 2021-05-01T17:11:55.220600Z

my question was more along the line: given the example at the end of, is what I'm doing even supposed to work?

william 2021-05-01T17:12:37.220800Z

no that prints undefined 😮

p-himik 2021-05-01T17:12:45.221Z

Well, there you go.

p-himik 2021-05-01T17:12:53.221200Z

Try with just [:> rcyto ...].

p-himik 2021-05-01T17:13:15.221400Z

If it works, simply rename rcyto to CytoscapeComponent or whatever you prefer.

william 2021-05-01T17:14:02.221600Z

no, it doesn't like the object it gets, apparently:

module$node_modules$react_cytoscapejs$dist$react_cytoscape.js:6 Uncaught TypeError: e.forEach is not a function
at least it's not undefined anymore

william 2021-05-01T17:15:26.221800Z

but rcyto is the right object, because it has the methods I would expect

p-himik 2021-05-01T17:15:29.222Z

That's a different error. And yeah, your code is incorrect. elements is very different from the original example.

william 2021-05-01T17:17:30.222200Z

when I say In react:

<CytoscapeComponent elements={elements} style={ { width: '600px', height: '600px' } } />
how would I pass both elements and style? Can I use something like:
{:elements ...
 :style ...}

p-himik 2021-05-01T17:18:34.222400Z


william 2021-05-01T17:23:19.222600Z

ok, everything works now, thank you so much for teaching me how it's done!