You can create a reagent component, export it, and then import it into your JS code.
Since you already have the web package / reaction in the js project, you need to exclude cljs from the project:
:dependencies [[org.clojure/clojure "1.8.0"] [org.clojure/clojurescript "1.9.229"] [org.clojure/core.async "0.2.391" :exclusions [org.clojure/tools.reader]] [reagent "0.6.0" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server]]]
Now you need to trick the Reagent into thinking that these reaction files that you just excluded are still here. Create these three files:
Src / cljsjs / react.cljs
(ns cljsjs.react)
Src / cljsjs / react / dom.cljs
(ns cljsjs.react.dom)
Src / cljsjs / react / home / server.cljs
(ns cljsjs.react.dom.server)
Yes, only one line with a namespace declaration in each file.
Now you can write your component:
reagent_component / core.cljs:
(ns reagent-component.core (:require [reagent.core :as r])) (def counter (r/atom 5)) (def ^:export test66 (r/create-class {:reagent-render (fn [props] (let [{:keys [name]} props] [:div {:on-click (fn [] (swap! counter inc))} name ", I am counting " (clojure.string/join ", " (map inc (range @counter)))]) )}))
Your cljsbuild section in project.clj
might look like this:
:cljsbuild {:builds [{:id "min" :source-paths ["src"] :compiler {:output-to "resources/public/js/compiled/reagent_component_min.js" :output-dir "resources/public/js/compiled/min" :main reagent-component.core :optimizations :advanced :asset-path "js/compiled/out" }}]}
For brevity, in the form I gave you only the min
section in cljsbuild.
lein cljsbuild once min
will create a resources/public/js/compiled/reagent_component_min.js
that should be copied to your Webpack project.
A new entry is added to your webpack.config in front of your main entry point:
entry: [`${APP_DIR}/reagent_component_min.js`, `${APP_DIR}/main.js`],
This file (reagent_component_min.js) should be excluded from babelification:
module: { loaders: [ { test: /\.js$/, exclude: /(node_modules|bower_components|reagent_component_min.js)/, loader: 'babel-loader', query: { presets: ['latest'] } } ] }
and in your javascript you use it like this:
import React from 'react'; import ReactDOM from 'react-dom'; const comp = reagent_component.core.test66; const element = <div>Hello, world {React.createElement(comp, {name: 'akond'})} </div>; ReactDOM.render( element, document.getElementById('app') );
Yes, the babel jsx plugin does not recognize <comp name="..."/>
. This is why React.createElement is called. I did not understand how to make it better, but it works.