Before I begin this tutorial, let me preface by stating what’s been written multiple times in regards to using jQuery with React: You shouldn’t do it. There are hundreds of posts everywhere on the web telling you the pitfalls of using jQuery with React and I completely agree with all those reasons. That being said, and you being here I’d assume that you’d like to ignore those warnings and for whatever reason still go ahead with the dirty deed. Having found very little content on the web that shows you the safest way to use the two libraries (aside from not using them together at all), I’ve decided to put together this little tutorial to show you how you can still use jQuery with React in a somewhat safe, uncompromising way.

 

In case you don’t know why it’s considered unsafe to use jQuery with React, I found the top answer on this post sums it up well. Both jQuery and React modify the DOM albeit in different ways: jQuery uses HTML selectors to manipulate the DOM whereas React has its own virtual DOM  which is manipulated with changes to state. The issue arises when jQuery modifies the DOM and React has no idea that something has changed which can cause conflicts between a component’s state and what the DOM is actually reflecting. That is why it’s often said that anything you’re trying to do using jQuery with React can probably and should be done purely using React. That’s why if it’s possible, it’s highly recommended you take the extra time to do things properly instead of the “somewhat hacky” way I’ll be showing you how to in a short while.

 

So, now that you know you’re about to go biking down a steep hill without functional brakes, allow me to at least fasten your helmet for you.

 

Phase 1 – Creating the React Components

 

We’ll start a new React project using npm create-react-app and delete everything out of the “./src” folder except for index.js and index.css.

 

delete project files

 

The goal of the project will be to create a grid with columns like “Name, Artist, Duration, Year” for songs and a list of songs beneath it. The column headers will be draggable and we’ll make sure that the data displayed beneath the headers is the right data based on which column it’s under. (Of course you could always use react libraries to do this but the point of this tutorial is to show you how you can “safely” do it using jQuery with React).

 

Now that we’ve deleted everything but the index files from the “/src” directory we’ll create a new React Component in the same directory as index.js with the name SongTable to simulate the “table” we are going to create ourselves.

 

 

I’m going to import the SemanticUI stylesheet to get some nice looking UI elements in the project. This can be done most easily by just including it your index.html file found in the “public” directory inside of your project’s file structure like so:

 

semanticui cdn

 

We’ll now write some code inside of our SongTable component to create some headers inside of some segments. One for each of our “column titles”: Name, Artist, Duration, and Year.

 

SongTable code

 

And if we run our project by opening a terminal window in VSCode(^~ on Mac) and typing “npm start” we can then navigate to localhost:3000 and see what it looks like:

 

headers

So far so good but we still haven’t made this “React-y” yet so let’s take our header names and throw them into our component state. From there we can render them out using the map() function like so:

variables in react state

 

As you can see this makes for much cleaner and concise code. To explain what’s going on in the code in case the syntax isn’t familiar is we’ve created a grid, that has a single row, and inside that single row will be four columns each with the header names in our state. The results look like this:

 

headers inside grid columns

Great, now let’s get started on our second component SongList. This component’s main role will be to quite literally render a list of songs. After creating the js file, we can render it in our SongTable. We’ll also pass through our column headers which we’ll use later to determine what song data to display in what order based on the columns.

 

songlist component being rendered in react

 

Let’s add some songs to our SongList state component and render them out using the map() function again.

 

list of songs being rendered in react

songlist render method in react

 

After adding a little color to the SongList classname and SongTable we get something that looks like this:

 

pretty nice grid there

Phase 2 – Inserting the jQuery

It’s now time for us to insert some jQuery into our project. Begin by navigating to the terminal, Ctrl-C to stop your server and then install jquery and jquery-ui by running the following commands:

 

npm i jquery --save
npm i jquery-ui --save

 

We’ll need jquery for the selectors and jquery-ui for the functions and ui elements we’ll be using in this project. Once they’ve finished installing you can import them into the file where we need them, in our case it’s SongTable.

 

importing jquery and jquery ui

 

As you might see from Line 4, we’ve imported a jQuery ui widget known as “sortable”. You can see the way it works here by allowing components to be dragged and dropped, very much like the way we hope to make our headers work.

 

Now stay with me, this is where things might get a little sticky. The first thing we’re going to do is take a look at the sortable documentation. Specifically, the source code for the placeholder example since it most mimics our end goal idea. Ignoring most of the code we are most concerned with 3 specific things inside the code.

 

jquery placeholder

 

The function code, the sortable id in the <ul> tag and the class code in the <li> tag. These are the sugar, spice, and everything nice we’ll need to create the perfect little jQuery components. I’ll add them to the code and explain what I’m doing and why I’m doing it.

 

 

componentDidMount jquery function in react

 

Here in lines 10-14 we’ve copy pasted the sortable function. Line by line this says:

10. componentDidMount() { // when our SongTable component has mounted

11.  $(function () {    // we will call a jQuery function

12a. $("#sortable") // the function we call will happen on all HTML elements whose id is "sortable"

12b. .sortable() // and that name of the function we will call is sortable()

 

So function’s out of the way, next we worry about the HTML.

 

sortable html id as react code

 

If we look at the API documentation for the jQuery ui sortable widget we see that “sortable” is the id we need to use for which html elements we want to be sortable. In our case, the overarching “row” is what we want to be sortable so we tack that onto line 27 as part of the id. The “ui-state-default” on line 29 tells jQuery “this is the element we want to be able to drag and drop”. Since I want the user to be able to drag and drop from anywhere in the box, I added it to the entire column. If I wanted just the header to be the area from which one could drag and drop, I would have added “ui-state-default” to the header className. I’ve also taken the liberty of adding a red border around the blue box so that I can more easily display the action of dragging and dropping, but you don’t need to do that to make it work.

red border in react styling

 

Here is what it looks like. Looks like we got that drag and drop action going on!

dragging and dropping

 

Phase 3 – Communicating between jQuery and React

 

Now that we’ve got both the React and jQuery running, we need to bridge the gap of communication between them. Remember earlier we said that jQuery and React both modify the DOM in different ways and as a result neither one has any idea what changes the other has done. That’s why it’s our job to make sure that there is a line of communication between both. The first thing we’re going to do to implement this line of communication is take a look at jQuery’s stop event. This is the event we want to focus on because it occurs after sorting has stopped aka once you’ve dragged and dropped. I’m going to add it to the code and explain line by line again.

 

jqeury stop function in sortable

 

Alright so there’s a couple things I’ve done here that don’t seem obvious right away, but I want to begin explaining them from the bottom-up starting with the html. In line 37 I’ve added an id with the value “columnheaders” to the blue segment. This will help with the jQuery selecting which I’ll explain in a bit. Line 41 now has an id too called “headerid” and a custom attribute I’ve added with the header name as its value.

jquery HTML code

 

The reason behind adding an id is because we are using the “ui header” className in both our SongTable and SongList React components. Since we don’t want our jQuery selecting the “ui headers” in our SongList component, we can add a unique id in our SongTable component which will make selecting our targeted headers much easier. The “headertitle” custom attribute lets me “extract” the header title (Name, Artist, etc.) from that <div> element. I’ll need this headertitle to get the new order of columns once it has been changed. If this sounds a little complicated don’t worry, it’ll make more sense when we get to the function.

 

Let’s get to the function.

 

stop in sortable jquery function

 

13. stop: function(even, ui) { // On the stop event

14a. $("#columnheaders .ui.header") // find every div with the columnheaders id and the ui header className

14b. .each(function(index) { // for each div you find with the columnheaders id and ui header className perform a new function

15. console.log($(this).attr("headertitle")) // log this div's "headertitle" attribute

 

Makes much more sense now right? No? Try running it with “npm start” and seeing what happens. If we drag the “Year” header and move it to the left in place of “Duration” we see this in the dev console:

console logging header columns

Look at that! Our jQuery works. We are getting the most up to date version of our headers in their proper order. All that’s left now is to tell React what we’ve done and notify it to change its own state.

 

Phase 4 – Re-rendering React

 

The first step in this phase is simple. Create a changeHeaders function so we don’t “clog” up the code. Next, we’re going to change our jQuery functions to use ES6 arrow notation. Now, we can use the this keyword in our code. Observe lines 14 and 16 below:

arrow notation functions in React

We can now call the changeHeaders() function on line 20 using this. Now, let’s make an array called newHeaders and add the new order of column headers to it. Then we can pass it to our newly created changeHeaders function like so:

adding new order of headers to array

 

Here’s what the console shows us when we drag and drop a header.

header drop

Now all we got to do is tell React to change its state using setState(). Since we have the new headers being passed through the changeHeaders() function this becomes a one-liner.

 

Setting State in react

 

And voila, we’ve successfully communicated to React after changing the DOM via jQuery. One final step remains, having the SongList data properly render based on what column it’s under. If we remember earlier, we passed the column headers from SongTable to SongList through the columnHeaders props. Therefore, SongList already has the most up to date headers. Now, we just need to add a bit of extra logic to our SongList code to make sure it displays the correct data. This can be done with two simple map functions.

 

Rendering the right columns in SongList

Essentially what our code is doing here is looping through every header, and based on what the headers name is it will display the proper song data. Try it out yourself and move some columns around to see the results.

 

Phase 5 – Profit

So there you have it. You’ve officiated an unholy matrimony between React and jQuery. I hope you’re prepared to deal with the consequences and if anyone asks you where you learned this from, don’t tell them it was me.