reagent

A minimalistic ClojureScript interface to React.js http://reagent-project.github.io/
2020-06-26T07:28:01.243400Z

Can you wrap the body of the let in a (fn [] body)

juhoteperi 2020-06-26T09:16:39.245500Z

People were asking about Framer-motion hera and on Github so I tested it with Reagent and at least this simple case works: https://github.com/reagent-project/reagent/compare/framer-motion-example

👍 1
👏 1
❤️ 1
🎉 1
2020-06-26T10:25:22.249200Z

Can anyone help me understand how to translate a component like this into a reagent one?

import ReactMarkdown from 'react-markdown';
import MathJax from 'react-mathjax';
import RemarkMathPlugin from 'remark-math';

function MarkdownRender(props) {
    const newProps = {
        ...props,
        plugins: [
          RemarkMathPlugin,
        ],
        renderers: {
          ...props.renderers,
          math: (props) => 
            <MathJax.Node formula={props.value} />,
          inlineMath: (props) =>
            <MathJax.Node inline formula={props.value} />
        }
      };
      return (
        <MathJax.Provider input="tex">
            <ReactMarkdown {...newProps} />
        </MathJax.Provider>
      );
}

export default MarkdownRender

2020-06-26T10:25:41.249600Z

I specifically don't quite know how to handle the renderers and with the return statement.

2020-06-26T10:51:49.260900Z

I always have the hardest time figuring out any kind of direct React interop in any non-trivial case.

2020-06-26T10:52:04.261300Z

The examples consist mostly of like [:> ReactComponent] and whee you're done.

juhoteperi 2020-06-26T10:55:48.262100Z

(defn markdown-render [props]
  [:> (.-Provider MathJax)
   {:input "text"}
   [:> ReactMarkdown
    (merge props
           {:plugins [RemarkMathPlugin]
            :renderers (merge (:renderers props)
                              {:math (fn [js-props]
                                       (r/as-element [:> (.-Node MathJax) {:formula (.-value js-props)}]))
                               :inlineMath (fn [js-props]
                                             (r/as-element [:> (.-Node MathJax) {:inline true :formula (.-value js-props)}]))})})]])

2020-06-26T10:56:24.263Z

@juhoteperi Thank you so much. Let me give this a try.

juhoteperi 2020-06-26T10:56:46.263900Z

... is just into or merge, not really React specific. Only gotcha is to use as-element or reactify-component or such with function in the props that need to return React elements

juhoteperi 2020-06-26T10:57:04.264400Z

As hiccup syntax within the function is not autoamtically converted by Reagent

juhoteperi 2020-06-26T10:57:40.265400Z

And note that props argument for those renderers is the js object

p-himik 2020-06-26T10:58:17.265600Z

There are 3 main things one has to understand in order to painlessly interop with React components - A difference between components, instances, and elements - When and how Reagent converts CLJS data structures into JS ones and vice versa - How exactly the props you pass to the underlying React components will be used Maybe I'm forgetting something - let me know.

2020-06-26T10:58:50.266500Z

@juhoteperi So in that case, how do you use markdown-render ? What has to be in props?

juhoteperi 2020-06-26T10:59:03.266900Z

markdown-render props is cljs map

2020-06-26T10:59:21.267300Z

@p-himik Yeah, despite having used reagent itself for a few years now, I don't have a great understanding of those things, unfortunately.

2020-06-26T11:01:56.268600Z

Wow, it works!

2020-06-26T11:02:04.269Z

Now I just have to dig into this example to really understand it.

juhoteperi 2020-06-26T11:02:07.269200Z

:> is unfortunately not very clear on what it converts. :r> or create-element is more obvious as you have to convert everything to JS objects yourself.

juhoteperi 2020-06-26T11:03:46.270900Z

With :r> and create-element it could look like this:

(defn markdown-render [props]
  [:r> (.-Provider MathJax)
   #js {:input "text"}
   [:> ReactMarkdown
    (clj->js (merge props
                    {:plugins #js [RemarkMathPlugin]
                     :renderers (clj->js (merge (:renderers props)
                                                {:math (fn [js-props]
                                                         (r/create-element (.-Node MathJax) #js {:formula (.-value js-props)}))
                                                 :inlineMath (fn [js-props]
                                                               (r/create-element (.-Node MathJax) #js {:inline true :formula (.-value js-props)}))}))}))]])

2020-06-26T11:04:29.271600Z

So the fundamental things I got wrong was: 1. not calling as-element on my return values from the renderers 2. Not knowing how to express "MathJax.Node" (for example) as (.-Node MathJax).

2020-06-26T11:04:44.271900Z

I didn't even know :r> existed!!!!

juhoteperi 2020-06-26T11:05:10.272100Z

Just in latest 1.0.0-alpha2

juhoteperi 2020-06-26T11:05:50.272500Z

It is probably only mentioned in the changelog and the issue

2020-06-26T11:08:24.272900Z

@juhoteperi Thanks again for your help. If I ever run into you at a clojure conference, I owe you the drink of your choice. 🙂

🍻 2