Light Speed Development With JQuery and ReactJS

Accelerate to the Speed of Light in Software Development Process

Posted by Heikki Kupiainen/Oppikone on 09.01.2017 19:56:36

Why jQuery?

jQuery is a widely used JavaScript library for DOM element manipulation, networking and much more. However, when you search for articles about combining jQuery with ReactJS you will find quite many postings written by ReactJS enthusiasts who declare that you should not use jQuery at all with ReactJS. Their reasoning goes usually that there is no need at all to manipulate DOM directly because with ReactJS, you never need to interact with real DOM directly since it is autogenerated from ReactJS's virtual DOM model. According to them, manipulating real DOM directly contradicts ReactJS's ideology and therefore should not be used at all. It sounds all reasonable, but I think that such view is a little misguided.

Those articles often forget jQuery is a lot more than DOM manipulation. For starters, jQuery offers all-powerful networking methods that are not covered by ReactJS. You can use jQuery to enable nice networking capability in your app. Or you can use something else as well. For those who dislike jQuery and want to use some other networking library, I would recommend to have a look at Axios. Well, now there are some parties who want to make ReactJS fatter and have started some projects to extend ReactJS bundling it with some networking. But how wise is that? Good luck with "rewriting in ReactJS" everything that has been coded in the world until now! But if you are lazy like me, you don't want to re-invent everything but just rather benefit from solutions that others have created before.

Just think about dozens of awesome UI libraries and components that already exist, for instance Kendo UI that is by far the leading UI library in the JavaScript world. Because Kendo is the best, I want to use Kendo for charting and many other aspects that it covers. You might have other preferences. You might like some other charting libraries. It is okay to feel that way. But I believe that you, if you think even a bit like me, don't have time to wait eons for some teenager to implement some luke warm "ReactJS-way"-imitation of your favorite library first. I want to use the best solutions that I know and I want to use them today.

Luckily, you can combine Kendo UI with ReactJS. And you can combine almost anything else with ReactJS. You can do it if you use jQuery. Because jQuery is an all powerful Swiss army knife of JavaScript UI development and if you apply jQuery, you can embed Kendo UI and everything else seamlessly into your ReactJS app. I am going to show that you can use jQuery ubiquitously inside your ReactJS app without contradicting ReactJS's ideology. Cross-breed ReactJS and jQuery, take the best of both solutions, accelerate your development to the speed of light!

Extending The Car App

I showed in my earlier article how to code a small app with ReactJS and callbacks. Let's extend that app a little to turn it into a good cornerstone for demonstrating Kendo integration with jQuery. The app will have two primary modes: one that is displayed when the user is not logged in and one that is displayed when the user is inside the app. When the user is logged out they must be provided with LoginView and when they are logged in they shall see the actual app, which I am going to call ManagementView. We'll modify our car app accordingly. The App component shall serve as a switch between these primary modes:

Note that render-function contains a very simple html snippet which is mainly a Bootstrap wrapper around the actual view component. In render-function, the state of the app is checked. if the user is logged in then the view component is initialized as ManagementView but otherwise as LoginView. At this point the App doesn't need to know anything else than whether the user has been authenticated and must be let in and whether they request to be logged out so the app can switch to LoginView mode. Therefore I couple LoginView's actíon fireLoginSuccess with callback handleLoginSuccess and ManagementView's action fireExitRequest with handleExitRequest. These handlers swap the App's state between logged in and logged out by updating loggedIn state accordingly.

Now let's have a look at ManagementView component:

A look at ManagementView's render function reveals the most of its purpose. It holds two components, a Navigation component and a view component. The view component is generated using createViewComponent method. In that method a decision is being made: if the user has already selected a car model ( this.state.selectedCarModel is true ) then the view component will be instantiated as a CarDetailView that displays some information specific to that very car. But if there is no car model selected then the view component will be instantiated as a CarFilterList. CarFilterList will allow the user to select a car.

Modularity Through Callbacks

This ReactJS app uses a simple callback technique to enable communication between components. It is a straightforward way to implement intercomponental communication and it's relatively simple to follow as well. Yet it has some caveats that justify a different approach called Redux. I will address the Redux way later on explaining in detail how it compares with a callback based approach.

In this callback-based implementation, see how CarFilterList is instantiated with some constructor parameters. These parameters define ManagementView's handleCarModelSelected as a callback fireCarModelSelected inside CarFilterList. It means that when CarFilterList "thinks" it is calling fireCarModelSelected, it will actually cause its parent component ManagementView to invoke handleCarModelSelected. So what's the difference? What we see here is actually a JavaScript equivalent of Java's interfaces. We can consider that the method fireCarModelSelected that CarFilterList "sees" is as an interface that ManagementView implements in handleCarModelSelected method. One cool thing about this approach is that it promotes modularity! CarFilterList can happily fire a "car model selected" message into the bit space without needing to care what actually happens somewhere else.

I also implemented a back button functionality here. ManagementView "listens" to Navigation component and handles backward navigation requests coming from there. For simplicity, I cheat here a little with back button functionality for now. Back button will be available only on CarDetailView an it will take back to ManagementView. This is achieved by unselecting the selected car. This state change will automatically lead to a view change which is certainly one strength of ReactJS approach. A proper way to implement back button functionality would be pushing view history into a stack and then popping them out one by one when back button is clicked. I'll address this issue later in more detail.

Now let's have a look at Navigation component:

Navigation view is pretty simple. But remarkable is here however that I injected click handlers to buttons using jQuery inside componentDidMount function. ComponentDidMount is an ideal intervention point for jQuery injection because it is invoked when ReactJS has already done its job and generated the actual DOM structure. That is the point where you can do further modifications to the DOM structure. ReactJS won't see this further manipulation. Many libraries are designed to be used together with jQuery and at this point it is safe to apply them without causing any complications inside React engine.

See the Navigation component in action! Just click the cars on the list and you'll see how the back button works:

Data - Where Did It Come From?

You may have noticed that the example app I showed contains a list of cars with some more detail about each car. If your app runs in a browser, ideally you load the data from a microservice over HTTP using jQuery. I'll be covering this subject later on in detail. But for this simple proof of concept, we'll have no problem to implement a mock data service with a hard-coded sample data. This enables you to push on to implement the client software even before the back end is ready. Then you can just replace your fake service with the real implementation that actually retrieves the data over HTTP. For more about this design pattern please check my article about Dependency Injection In JavaScript. For now, let's have a look at our data service placeholder:

While this vanilla data service implementation serves well enough our demo app, please consider achieving business-grade data integrity and have a look at my article about Redux.

What's Next?

In this article, I hightlighed advantages on conceptual level that jQuery can provide for your app. I also showed that it is possible to inject jQuery capability into a ReactJS app. But this is just the starting point for all fun! Next time, I'll show how you can use jQuery to empower your app with strong networking capabilities and turn it into a serious business class tool with professional widgets! I'll be back to you soon!