DEV Community

Sasha Blagojevic for JSGuru

Posted on • Originally published at jsguru.io

Leaving the Old Ways - jQuery vs React

Main Image, React logo on thumbs up
Contrary to popular belief, React’s biggest use cases are not SPAs, it’s the hybrid apps that are most common, and the best fit in my opinion, in this post I will cover how and why I went from a React hater to a React fanboy, and why React is a perfect replacement for jQuery.


I used to have some kind of an inner resistance when React and Vue first started to gain traction and were becoming the de facto standard for building modern UIs.

Yes, I’m purposefully leaving Angular out, even though AngularJS was the pioneer of the front end revolution that brought us web 2.0.

Angular is philosophically on the completely opposite side of the spectrum, it’s a full-blown SPA framework, whereas React is just a view library, and I’m still not convinced SPAs are the right way and personally I prefer the hybrid approach.

For all of you that are thinking right now  - “And what about Vue?” , Vue would be somewhere in between these two extremes.

Contrary to popular belief, React’s biggest use cases are not SPAs, it’s the hybrid apps that are most common, and the best fit in my opinion. Don’t believe me? Well look what Facebook’s Dan Abramov had to say:

It’s interesting that React became associated so much with SPAs but Facebook isn’t using it for SPAs (except for the Instagram website and some internal tools) - @dan_abramov

One of my major pet peeves was Webpack and all the tooling they brought with themselves.

I held a strong opinion that they were introducing unnecessary complexity to the front end, yes they made us developers feel like rocket scientists with the amount of tweaking we had to do and the number of levers and gears we had to pull and turn to make them run, but at the end of the day, did they really add value to the business?

Did they improve the product and the user experience to warrant a higher maintenance and development cost and a higher barrier of entry for new bloods, when we could have done the same with plain ole jQuery, or even better, vanilla JS?

After I found out React introduced react-cli I decided to give it another go, and boy oh boy was I pleasantly surprised.

With the introduction of react-cli (and vue-cli) all that nitty-gritty tooling and those build steps that were equivalent of getting a PhD in Computer Science were out of the way for 80–90% of use cases, although you still had to roll up your sleeves and mess around with webpack for some edge cases.

Sure if you’re building something fairly simple, may it be a contact form with an Ajax submit or something entirely different but that is simple enough, vanilla JS is, in my opinion, a sound approach, there is no need to roll out the big guns. You can even go with jQuery, but there is really no need for it in today’s world, but that’s a completely different topic.

Keep it simple  -  this should always be your mantra.

In that case, if you were to use a framework, 90% of your code would be the frameworks infrastructure and the rest would be your actual logic. That is a major overkill, you are introducing unnecessary boilerplate and increasing your bundle size which directly impacts performance. Bigger bundle means a lot more bytes have to be sent over the INTERNETZ, so you’re actually costing your business, just because you wanted to use that shiny new thing.

Oh, you think those milliseconds don’t matter much? Well they can quickly add up, especially on high traffic sites, just because today’s machines are powerful doesn’t mean we should be reckless and throw anything at them, we need to be conservative with our resources.

Look at it like this, it’s as if you are building a foundation for a ten story building only to put a tent on it.

React, versus the old way, really comes to shine when you are building complex UIs.

With React the simplicity of development increases with the complexity of the UI you are building, or in other words, the cost of development is inversely proportional to the complexity in comparison with the vanilla JS/jQuery approach.

Here’s a little graph for all you visual types.
Graph representing how the simplicity of implementation increases with the complexity of your UI when using React

Talk is cheap, let’s get our hands dirty with an example from the real world.

We have an invoice form, aside from the general data like the date of the invoice, the due date of the invoice, subject etc., the user needs to be able to add/remove invoice items.

Invoice items, on the other hand, have the following:

  • name and/or the description of the product/service you’re invoicing,
  • it's quantity,
  • price,
  • any discount you may give,
  • any penalty interest that incurred,
  • then we might have VAT tax or sales tax depending on your country’s laws

and finally, all the calculations that go with the aforementioned.
Image representing a complex form
You see now how a seemingly simple thing can get complicated quickly?

With the old approach, you would have to have a lot of things on your mind, you would need to:

  1. Add change event handlers on all the different input fields, and some of them would additionally need to cancel each other out so you would need to track when to detach them.

  2. Every time an invoice item is added or removed you would need to manipulate the DOM, by either adding or removing child nodes or writing HTML as a string.

    No matter the choice, you’d need to concatenate some HTML and fill it with variables, which can get unruly pretty fast. ECMA 6 string literals do ease this a bit, but still, it can get cumbersome.

    Imagine a designer changes something, on how many places would you need to changes all those bits that you’re glueing together in your vanilla JS code?

    Another thing you would need to keep in your mind is that if you manipulate DOM as a string you’re killing all the event handlers on those particular DOM elements. Yep, another gotcha moment.

  3. Calculations  -  every time an invoice item is added or removed you need to calculate its particular values and in addition update the invoice’s subtotal, tax, total, etc. Essentially you would be creating your own state store.

I probably might have missed a thing or two that would pop up while trying to handle this use case the old way, as it usually is, everything sounds simpler on paper until you start to implement it and a whole new spectrum of cases that need to be handled appears.

Using React requires a slight shift in your mindset, in a nutshell, you only need to be concerned with one thing, the state. This simplifies the logic immensely, you are only concerned about your state, that is the only thing you need to manipulate, and your invoice input fields and invoice items will be re-rendered according to the changes in your state.

Let’s take a look at our simplified code example, this might give you a clearer picture.

import React from "react";
import ReactDOM from "react-dom";
import PropTypes from "prop-types";

class InvoiceItemForm extends React.Component {

  constructor(props) {
      super(props)

      this.state = {
          itemInput: {
              description: '',
              quantity: 0,
              price: 0,
              subtotal: 0,
              taxRate: 0.17,
              tax: 0,
              total: 0
          },
          invoiceItems: []
      }

      this.handleInputChange = this.handleInputChange.bind(this);
      this.addItem = this.addItem.bind(this);
      this.removeItem = this.removeItem.bind(this);
  }

  handleInputChange(e) {
      let input = (e.target || e.currentTarget);
          input.subtotal = input.price * input.quantity;
          input.tax = input.subtotal * input.taxRate;
          input.total = input.subtotal * (1 + input.taxRate);

      this.setState((state) => { return state.itemInput[input.name] = input.value; });
  }

  addItem() {
      let state = this.state;
          state.items.push(state.itemInput);

          // Clear the last input
          for (let key in state.itemInput) {
              switch (key) {
                  case 'description'
                      state.itemInput[key] = '';
                      break;
                  case 'taxRate':
                      state.itemInput[key] = 0.17;
                      break;
                  default:
                      state.itemInput[key] = 0;
                      break;
              }
          }

      this.setState({itemInput: state.itemInput, items: state.items});
  }

  removeItem(e) {
      let rowIndex = (e.target || e.currentTarget).parentNode.parentNode.rowIndex;

      let items = this.state.items.filter((item, i) => { return i !== rowIndex; });

      this.setState({items : items});
  }

  renderCells(item, rowIndex) {
      let cells = [<td>{rowIndex + 1}</td>];

      let i = 1;
      for (let key in item) {
          cells.push(<td key={i}>{item[key]}</td>);
          i++;
      }

      cells.push(
          <td>
              <button onClick={this.removeItem}>
                  {'Remove Item'}
              </button>
          </td>
      );

      return cells;
  }

  render () {
    return (
        <React.Fragment>
            <div>
                <input
                    name={'description'}
                    value={this.state.itemInput.description}
                    onChange={this.handleInputChange} />
                <input
                    name={'price'}
                    value={this.state.itemInput.price}
                    onChange={this.handleInputChange}>
                <input
                    name={'quantity'}
                    value={this.state.itemInput.quantity}
                    onChange={this.handleInputChange}>
                <input
                    name={'taxRate'}
                    value={this.state.itemInput.taxRate}
                    onChange={this.handleInputChange}>
                <input
                    name={'subtotal'}
                    disabled={true}
                    value={this.state.itemInput.subtotal}
                    onChange={this.handleInputChange}>
                <input
                    name={'tax'}
                    disabled={true}
                    value={this.state.itemInput.tax}
                    onChange={this.handleInputChange}>
                <input
                    name={'total'}
                    disabled={true}
                    value={this.state.itemInput.total}
                    onChange={this.handleInputChange}>
            </div>
            <table>
                <thead>
                    <tr>
                        <th>Item no.</th>
                        <th>Description</th>
                        <th>Price</th>
                        <th>Quantity</th>
                        <th>Tax Rate</th>
                        <th>Subtotal</th>
                        <th>Tax</th>
                        <th>Total</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    {
                        this.state.items.map((item, i) => {
                            return (
                                <tr key={i}>
                                    {this.renderCells(item, i)}
                                </tr>
                            );
                        })
                    }
                </tbody>
            </table>
        </React.Fragment>
    );
  }
}
export default InvoiceItemForm
Enter fullscreen mode Exit fullscreen mode

Vuoala, that’s it!

Hey, do you have a jQuery app you would like to migrate or are you just trying to figure out which framework would be best for your next million dollar idea? Contact us at info@jsguru.io, and let that be our headache.


Before you go…

If you enjoyed reading this post please share it. You should check out our other publications, you might like them too! We write from time to time about software development, tips and tricks, and how to become a better developer and business person in general. Join us on the journey of constant improvement!

Follow us on Facebook, Twitter, LinkedIn, Medium or DEV.to.


Originally published at jsguru.io.

Top comments (9)

Collapse
 
jonrandy profile image
Jon Randy 🎖️

I've seen many, many projects where React has been used and it simply wasn't necessary - simple forms with a couple of buttons/controls, or simple websites with minimal functionality. The same thing could have been achieved with a mere fraction of the code using plain old vanilla JS.

This seems to be getting more and more prevalent these days. People are starting off with React and assuming it is the best way to do everything - it isn't.

Horses for courses - sure, it's the right tool for some projects, but in many cases it is simply overkill - over-engineering through ignorance

Collapse
 
blackcat_dev profile image
Sasha Blagojevic • Edited

Yep, I've seen people build blogs with server-side rendered React, that had no special JS effects or controls to warrant it, they made a full circle lol. They could have done the same with a couple of lines of PHP. Complexity for the sake of it! :D

Collapse
 
chartinger profile image
Christian Hartinger

Aside from pages where plain javascript is enough I would argue that vue.js in many cases would be an easier replacement for a jQuery app. No need for webpack, build chain and so on - just include it like jQuery and be able to use a modern (what ever that means) framework.

Collapse
 
jonrandy profile image
Jon Randy 🎖️

Yup. Riot.js is also a great option

Collapse
 
qm3ster profile image
Mihail Malo

Next thing, you're going to say you don't use React to generate static pages. -_-

Collapse
 
blackcat_dev profile image
Sasha Blagojevic

Vue is great as well, I haven't tried it personally, only glanced over it a bit, because React clicked with me so I stuck with it. For anyone looking to replace jQuery with Vue I highly recommend following @sarah_edo on twitter

Collapse
 
blackcat_dev profile image
Sasha Blagojevic • Edited

Yep, that one was a gem, you could say I'm a bit late to the game, I was kept in the back end dungeon for too long :D

Collapse
 
michaelrgalloway profile image
michaelrgalloway

React is becoming "the old way" already. Time for another blog post.