ClojureScript for the DevExtreme React Grid

I had a question recently about ClojureScript and how easy it would be to use the DevExtreme React Grid with that language and environment. ClojureScript is a functional language, which is a concept that works very well with React.

The CLJSJS repository provides an easy way for ClojureScript developers to depend on JavaScript libraries (in their own words), but JavaScript libraries need to be packaged and maintained in a specific format for this to work. I’m leaving this approach for later, since right now the React Grid has not reached a full release yet.

Requirements to build or try the demo

You will need both a working Node environment and an installation of Leiningen. Follow the two links in the previous sentence for installation files and instructions – both are quick and very straight-forward and you shouldn’t run into trouble.

How to build the demo yourself

Of course you can skip this part and just get the whole thing from github – in that case scroll down to find the instructions for running the demo. If you would like to do it yourself, read on.

The steps I followed are based on the post linked above, but I will also describe the demo code itself.

Project setup and library import

1 — Set up the project

Use this command to create a new project (feel free to modify the name of course):

lein new reagent-frontend demo-dx-react-grid-clojurescript

Now initialize the project with a Node package.json file (it’s okay to accept all the defaults):

Create the file src/js/main.js with the content below. This is the main file used by webpack, and it configures all the JavaScript dependencies to be made available in the window context. It also means that webpack finds the actual requirements and includes the correct packages in the bundle.

For simplicity, add a build entry to the scripts section of package.json and remove the test entry. Your scripts section should look like this:

...
"scripts": {
"build": "webpack -p"
},
...

Now run the build script to generate the bundle:

npm run build

3 — Modify project.clj for the bundle

Edit the file project.clj. First, change the dependencies block (within the first few lines) to the following to make sure that Reagent uses React and ReactDOM from the bundle in place of its own versions.

Second, insert the following block right behind both lines starting with :optimizations. This changes both compiler profiles to include the bundle instead of the standard CLJSJS libraries for React and ReactDOM. (Note that it is correct for the ReactDOM name to read cljsjs.react.dom, i.e. with a . (dot) instead of a dash.)

The React Grid requires some Bootstrap stylesheets and font files to work correctly. It should be possible to include these in the bundle, but I went the easier way here to include them separately, not least because the Grid also supports Material UI as an alternative UI platform.

Copy the stylesheets and font files to the public directory (use Windows copy andmd commands if you are indeed on Windows):

The first block of code in the function defines a few local values using let. This call retrieves the object deps.dx-react-grid from the window context (where the webpack main.js put it previously):

(aget js/window "deps" "dx-react-grid")

The same thing is done with the line that assigns the bs3 value. From these two top level JavaScript objects, the SortingState, LocalSorting, Grid, TableView and TableHeaderRow objects can be retrieved, and they are stored in Clojure values.

As the final part of the let instruction, columns and rows are populated for demo purposes.

The home-page function renders a result using the slightly extended Hiccup syntax implemented by the Reagent interface library for React. For example, this line begins rendering the Grid component, passing the previously arranged values as columns and rows React properties:

[:> grid {:columns columns :rows rows}
...

The nested elements are rendered using similar syntax and follow the normal structure of the React Grid. I have included an event handler on the SortingState (or sorting-state) for illustration purposes.

Running the demo (mine or yours)

If you cloned my project, you will need to build the JavaScript bundle before running the demo. If you were following the steps to do it yourself, you should have already done this above. These are the required commands:

npm install
npm run build

With the bundle available, you can then run the demo by executing this:

lein figwheel

The command instructs Leiningen to run the project using the figwheel environment. On the console, you will see a few downloads of required components, a compilation step, hopefully no error messages (please check, especially in case things go wrong!) and finally this line:

Prompt will show when Figwheel connects to your application

At the same time, Figwheel tries to open the main page of the application in the browser. This works fine for me, but just in case you don’t see a browser page coming up, you can open it manually by connecting to http://localhost:3449 or opening the file public/index.html.

When the browser page loads, Figwheel changes its prompt to read app:cljs.user=>, which means that the built-in REPL is ready for interaction.

The browser should now show the working React Grid with three rows of demo data. Functionality is limited because I included only a few basic plugins - feel free to play around and extend, and let me know if you encounter any issues!

What would be the reason for someone to use this instead of normal ES6/JSX?

23 August, 2017

Oliver Sturm (DevExpress)

Mohamed,

Reasons for using ClojureScript certainly vary, but the main point about it is that functional programming techniques are very common in the JavaScript world these days, from basic patterns all the way to functionally oriented libraries like React, and that JavaScript itself doesn't make it as easy as you'd wish to adhere to those principles.

I like ClojureScript myself, for the reasons I've already mentioned. It facilitates the programming style I like to use anyway (that's FP) and that works great with my favorite JavaScript platforms today (that's React, Redux etc), and by enforcing this style it helps me write more maintainable code than I would probably achieve by trying to follow FP approaches using JavaScript alone.