{"id":3594,"date":"2016-09-23T11:47:01","date_gmt":"2016-09-23T17:47:01","guid":{"rendered":"http:\/\/benincosa.com\/?p=3594"},"modified":"2016-09-23T11:47:01","modified_gmt":"2016-09-23T17:47:01","slug":"clojurescript-cljs-reactjs-re-frame-and-reagent","status":"publish","type":"post","link":"https:\/\/benincosa.com\/?p=3594","title":{"rendered":"Clojurescript (CLJS) &#8211; ReactJS, Re-Frame, and Reagent"},"content":{"rendered":"<p>I&#8217;ve been using <a href=\"https:\/\/github.com\/Day8\/re-frame\">Re-frame<\/a>\u00a0pretty extensively these last few weeks as we begin to work on the front end of our horrendously stylized project called <a href=\"http:\/\/ciscopipeline.io\">Pipeline<\/a>. \u00a0It has been pretty tough to get the hang of but after being stubborn enough not to change my mind once going down this road I&#8217;m really starting to come around &#8230; and dare I say, actually understand how to make it work!<\/p>\n<h2>What&#8217;s the Big Idea?<\/h2>\n<p>There are a few components to what I&#8217;m talking about that I&#8217;ll go over below. \u00a0The big idea though is that web applications today are a big mess of javascript, html, and CSS that is somehow stitched together. \u00a0Most of todays web applications aspire to be Single Page Applications (or SPA if\u00a0you are into that whole brevity thing). \u00a0Several frameworks have emerged with the (arguably) popular ones being Angular.js (from Google) and React.js (from Facebook). \u00a0The big picture though is: \u00a0How do you create a great Web front end to your application? \u00a0These frameworks typically call the APIs of a web backend which (hopefully) would be the same backend that a mobile application would call.<\/p>\n<h3>Clojurescript<\/h3>\n<p><a href=\"https:\/\/github.com\/clojure\/clojurescript\">Clojurescript<\/a> is a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Lisp_(programming_language)\">LISP language<\/a>. \u00a0It&#8217;s basically the same language\/syntax as Clojure but where as Clojure compiles down to Java, Clojurescript compiles down to Javascript. \u00a0Why would you want that? \u00a0Seems like overhead. \u00a0Well, the claim is that the Google closure compiler (confusing name) is much more efficient and can make it faster.<\/p>\n<p>What is interesting to me as I go down this route is that most of the blog posts are from 2014 and earlier and I can&#8217;t tell if I&#8217;m pursuing a path that is no longer cool or what. \u00a0This is surprising to me because with the greater popularity of React these days this seems like a great path.<\/p>\n<p>The downside to clojurescript is the stack traces are difficult to comb through and understanding the whole immutability thing can be a struggle.<\/p>\n<h3>React<\/h3>\n<p><a href=\"https:\/\/facebook.github.io\/react\/\">React<\/a> is Facebook&#8217;s Javascript library for creating user interfaces. \u00a0The idea is that there is a virtual dom and it listens to changes in data (binds to data) then will respond immediately to the changes. \u00a0It&#8217;s funny that after using the library through Reagent I still don&#8217;t really understand React. \u00a0To me its just the data changes and the web page is immediately updated.<\/p>\n<p>It should be noted that React isn&#8217;t a full on featured library like Angular so some people say its unfair to compare them. \u00a0But I tend to like <a href=\"https:\/\/medium.freecodecamp.com\/angular-2-versus-react-there-will-be-blood-66595faafd51?gi=3677380e0cf5#.6nan13r2z\">this blog&#8217;s argument<\/a> of why you can. \u00a0And in my limited knowledge of things in the world am easily persuaded by his post. \u00a0(Or should I say, enjoy that he has validated my decision). \u00a0I especially like the &#8220;unix philosophy&#8221; argument that takes the position of: &#8220;Your tool should do one thing very well&#8221;.<\/p>\n<h3>Reagent<\/h3>\n<p>So you have React and you have Clojurescript and you want to make awesome happen. \u00a0So naturally people create frameworks to make this happen for you. \u00a0Om, Rum, and some others emerge and I think are still out there. \u00a0I settled on Reagent though cause it seemed pretty simple and easier for me to wrap my head around. \u00a0<a href=\"https:\/\/github.com\/reagent-project\/reagent\">Reagent<\/a>\u00a0uses the <a href=\"https:\/\/github.com\/weavejester\/hiccup\">hiccup<\/a> syntax so it gets rid of having to do html tags and makes it easier to see. \u00a0When I used Ruby on Rails I would use <a href=\"https:\/\/github.com\/haml\/haml\">HAML<\/a>\u00a0which was the same concept.<\/p>\n<p>The result is that now when you are writing the application everything is in one language! \u00a0There&#8217;s no sprinking of HTML and not mixing with Javascript, its all just Clojurescript! \u00a0This is the thing I most love about it. \u00a0Its more akin to me like designing an iOS application in swift where there is one language to do it all.<\/p>\n<p>The other powerful aspect of Reagent is that it is functional. \u00a0Functional Reactive Programming (or FRP) means that interfaces respond to the data. \u00a0Or, &#8220;everything is data derived&#8221;. \u00a0There&#8217;s no ngThis or ngThat, it&#8217;s just functional stuff.<\/p>\n<p>The issue with Reagent (or lack of design feature) is that it is silent on how to store data and interact with data (client side) as well as serverside. \u00a0This is where the grand daddy of them all comes into play: \u00a0Re-Frame<\/p>\n<h3>Re-Frame<\/h3>\n<p>I started with examining the <a href=\"https:\/\/github.com\/Day8\/re-frame\/blob\/master\/README.md\">README<\/a> file on the <a href=\"https:\/\/github.com\/Day8\/re-frame\">Re-Frame<\/a> project and was immediately blown away. \u00a0Yes! \u00a0This is the most epic readme of all projects. \u00a0The examples and docs were pretty clear and quite glorious. \u00a0I loved the opinionated nature of it and the humor. \u00a0(not the best reason to pick a framework, but not bad!)<\/p>\n<p>Re-frame is a framework that works with Reagent to create the idea of a clientside database. \u00a0(Or a database that lives in the browswer). \u00a0It makes things fast and helps with state changes. \u00a0It has the idea of subscribing to changes or dispatching changes to the database realizing that everything can be asyncronous but everything responds to changes in the data. \u00a0Data all the way down.<\/p>\n<h2>An Example<\/h2>\n<p>I put an example on <a href=\"https:\/\/github.com\/vallard\/Reagent-Example\/tree\/master\/testme\">github<\/a> that you can see if you want to run for yourself.<\/p>\n<p>The idea is that you have a list of names and you want to filter them in the search bar. \u00a0Here&#8217;s the main entry code that is called from the main reagent code that initializes this home page.<\/p>\n<pre class=\"lang:clojure decode:true \">(defn show-home\r\n  []  \r\n  ;; First, display banner and search text box.\r\n  (let [search-string (r\/atom \"\")]\r\n    (fn []\r\n      [:div {:class \"jumbotron \" }\r\n        [:div {:class \"container-fluid\"}\r\n            [:div {:class \"row\"}]\r\n              [:div {:class \"col-sm-2\"}]\r\n              [:div {:class \"col-sm-8\"}\r\n                [:h2 [:center \"Fun names\" ]]\r\n                [:p {:class \"center\"} \"Filter names\" ]\r\n              [:div {:class \"row\"}]\r\n              [:div {:class \"col-sm-2\"}]\r\n              [:div {:class \"col-sm-8\"}\r\n                [:input.form-control {\r\n                  :type \"text\"\r\n                  :placeholder \"Filter names\"\r\n                  :value @search-string\r\n                  :on-change #(reset! search-string (-&gt; % .-target .-value))\r\n                }]\r\n           ]\r\n          ]\r\n      ]   \r\n    [:div {:class \"page-header\"}]\r\n    [display-names @search-string]])))<\/pre>\n<p>I have several bootstrap tags in there that I took out of the code. \u00a0The tricky thing is to notice the reagent r\/atom which is the data that changes. \u00a0This code doesn&#8217;t have any re-frame code to it. \u00a0Basically it displays a form. \u00a0Notice the code at the bottom to call display-names. \u00a0That code is where the filtering happens. \u00a0When the input is changed, the search-string changes. \u00a0You never have to re-call display names as its always called and responds to changes in data. \u00a0So great!<\/p>\n<pre class=\"lang:clojure decode:true \">(defn display-names\r\n  \"Displays APIs that match the search string\"\r\n  [search-string]\r\n    [:div {:class \"container-fluid\"}\r\n     [:center\r\n      (for [person-name names]\r\n        ;; tricky regular expression to see if the search string matches the name\r\n        (if (or (re-find (re-pattern (str \"(?i)\" search-string)) person-name)\r\n                (= \"\" search-string))\r\n          ^{ :key (.indexOf names person-name)}\r\n            [:div {:class \"col-sm-4\"}\r\n            [:div {:class \"panel panel-default\"}\r\n              [:div {:class \"panel-heading\"} person-name]]]))]])<\/pre>\n<p>Above is the display names code that takes a list of names (defined outside the function in the def (or variable ) called &#8220;names&#8221;. \u00a0It goes through and prints a name if it matches the filter.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been using Re-frame\u00a0pretty extensively these last few weeks as we begin to work on the front end of our horrendously stylized project called Pipeline. \u00a0It has been pretty tough to get the hang of but after being stubborn enough not to change my mind once going down this road I&#8217;m really starting to come&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[166],"tags":[845,844,841,843,842],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/posts\/3594"}],"collection":[{"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/benincosa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3594"}],"version-history":[{"count":1,"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/posts\/3594\/revisions"}],"predecessor-version":[{"id":3596,"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/posts\/3594\/revisions\/3596"}],"wp:attachment":[{"href":"https:\/\/benincosa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3594"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/benincosa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3594"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/benincosa.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3594"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}