This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-09-21
Channels
- # announcements (51)
- # asami (5)
- # babashka (25)
- # babashka-sci-dev (26)
- # beginners (33)
- # calva (10)
- # clj-kondo (51)
- # clj-yaml (99)
- # clojure (96)
- # clojure-australia (3)
- # clojure-berlin (5)
- # clojure-europe (151)
- # clojure-norway (58)
- # clojurescript (20)
- # cursive (13)
- # datalevin (1)
- # datomic (19)
- # docker (6)
- # emacs (55)
- # events (1)
- # fulcro (50)
- # gratitude (8)
- # juxt (7)
- # leiningen (5)
- # malli (6)
- # membrane (1)
- # nbb (28)
- # off-topic (22)
- # pathom (7)
- # polylith (20)
- # portal (1)
- # reagent (37)
- # reitit (2)
- # releases (2)
- # reveal (32)
- # scittle (34)
- # shadow-cljs (46)
- # testing (10)
- # tools-deps (33)
- # xtdb (18)
Hi me again, struggling with a translation issue from a react example into reagent hiccup. I can't quite understand how the props example given in the docs would translate from something like this -
const Page = React.forwardRef((props, ref) => {
return (
<div className="demoPage" ref={ref}>
/* ref required */
<h1>Page Header</h1>
<p>{props.children}</p>
<p>Page number: {props.number}</p>
</div>
);
});
function MyBook(props) {
return (
<HTMLFlipBook width={300} height={500}>
<Page number="1">Page text</Page>
<Page number="2">Page text</Page>
<Page number="3">Page text</Page>
<Page number="4">Page text</Page>
</HTMLFlipBook>
);
}
I'm trying to explicitly pass the props as in the example which is not something I've had to think about with reagent before
and I took the r/current-component method from this https://github.com/reagent-project/reagent/blob/master/doc/InteropWithReact.md
The React code that you've provided is written using Reagent as simple as:
(defn page [{:keys [ref number]} & children]
[:div {:class :demoPage, :ref ref}
[:h1 "Page Header"]
(into [:p] children)
[:p "Page number: " number]])
(defn my-book []
[:> HTMLFlipBook {:width 300, :height 500}
[page {:number 1} "Page text"]
[page {:number 2} "Page text"]
[page {:number 3} "Page text"]
[page {:number 4} "Page text"]])
Haven't tested but I'm pretty sure that that ref
will work just fine if you actually use it.Thank you for spending time and taking a look. I don't totally understand why that works though, is the link I was referencing outdated?
You shouldn't try translating things verbatim - it will invariably end bad in many cases because you will be using JS/React idioms in the CLJS/Reagent world. Instead, think of what's going on and how to replicate the behavior in Reagent.
Then the best approach would be to ask a more concrete question, including what library you're trying to use and what code you have come up with so far. More often than not the solution is something extremely simple, like adding an extra as-element
or preventing props serialization.
Fair enough, I really do appreciate that you took the time to help. In these situations I try to ask the least specific thing that seems to be the issue, so that I can understand the overall concept. Otherwise the friction that I'm getting here will reoccur every time I attempt something similar.
The library that I'm trying to use in this instance is here - https://www.npmjs.com/package/react-pageflip it creates a bit of animation
currently getting an error - React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined etcetc
(defn p [{:keys [ref number]} & children]
(fn []
(let [!page (r/atom nil)]
[:div {:class :demoPage, :ref (fn [ref] (reset! !page ref))}
[:h1 "Page Header"]
(into [:p] children)
[:p "Page number: " number]])))
(defn my-book []
[:> pf/HTMLFlipBook {:width 300, :height 500}
[p {:ref 1 :number 1} "Page text"]
[p {:ref 2 :number 2} "Page text"]
[p {:ref 3 :number 3} "Page text"]
[p {:ref 4 :number 4} "Page text"]])
Ah, crap - HTMLFlipBook
uses React.cloneElement
and assigns its own ref
under the hood. Really hate stuff like that.
Here's an example of how to use forwardRef
with Reagent: https://github.com/reagent-project/reagent/blob/059b26d07ab6dd0145739a6d22bb334ca4f05c1a/examples/react-mde/src/example/core.cljs#L71-L79
Not sure what you mean. In your case, it should be something like
(def page
(react/forwardRef
(fn page [^js props ref]
(r/as-element [:div {:ref ref}
[:p (.-children props)] ;; Try `(into [:p] ...)` if this doesn't work.
...]))))
Right, that page
is a React component and has to be used like one.
But Reagent itself would wrap those [page ...]
Hiccup vectors with as-element
. And you don't need that wrapping.
One way to do it would be to use r/create-element
inside a React component wrapped in a Reagent component, something like
(defn -my-book []
(r/create-element pf/HTMLFlipBook
#js {:width 300, :height 500}
(r/create-element page #js {:number 1} "Page text")
...))
(defn my-book []
[:> -my-book])
Maybe there's a better way, not sure.sorry, only just had a chance to try and I'm still getting Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
Are there any tools that can help diagnose what's happening with the import? If i (js/console.log pf) which is the library, it returns an object which is itself a react forwardRef. But the supposed component class is nowhere to be found i.e HTMLFlipBook isn't available within it - not even hidden behind pf/default
Your browser's debugger is the best thing here. You can tell it to break on an exception - that's how I'd do it.
If you won't be able to make it work - create a minimal reproducible example that includes all the steps necessary to build and run it and I'll take a look.
Hi, React and npm interops are quite confusing, I also used to struggle with it too although the final solution is often simple.
There are few mistakes in the snippet you sent.
First, react-pageflip is in common js style, so you have to import it like ["react-pageflip" :as HTMLFlipBook]
. That's why you get the "but got: undefined" error.
Second, react/forwardRef needs a react component, so you have to transform the hiccup form with r/as-element like this :
(def Page
(react/forwardRef
(fn [props ref]
(r/as-element
[:div.demoPage {:ref ref}]))))
Finally, as react/forwardRef gives you a React component, you have to use it as one:
[:> HTMLFlipBook {:width 300 :height 500}
[:> Page {:number 1} "Page text"]
; others pages
Since it's been two days I ping you @U2EJEK2SX else I'm not sure how quickly you would see this
Hi @U01V2D5ALKX, thank you for taking the time to explain, really informative, cheers!