React and jQuery do not play nicely

React and jQuery do not play nicely. That is by design.

Recently I was attempting to implement modal functionality into our Revision.net project.

I was in a rush, and went ahead with trying to implement Semantic UIs modal offering as quickly as possible.

Semantic UIs Javascript functionality relies heavily on jQuery. At first sight this did not seem like any kind of issue to me. I simply created a Reactive modal component which I defined a reference on. I then created an onClick handler on a button such that when clicked the modal was launched (using jQuery).

This worked. I continued with my life.

Unfortunately however this only worked because of the specific implementation. It was not correct, and does not make sense in the context of Reactive development.

The reason why is simple - React works on the basis of monitoring a virtual DOM and manipulating the real DOM. It is efficient because it only updates the real DOM with changes - when the state of a stateful component changes only the things that need to be updated are.

This is the reason why React asks that you define key properties when iterating through an array and outputting content for example. The key property allows React to monitor the output for that particular iteration such that if the data changes it can update what is displayed to the user.

The reason why jQuery and React do not play nicely is now most likely obvious.

When we execute:

$('.ui.modal').modal('show');

OR

$(this.modalRef).modal('show');

Semantic UI is explicitly manipulating the DOM. Be it adding classes, changing inline styles, or adding content. This means that the virtual DOM that React is aware of differs to what is actually presented to the user. React cannot reconcile changes any longer.

I only noticed this when I started to receive console error logs stating Failed to execute 'removeChild' on 'Node'. The reason I had not seen these errors previously was because I was launching the modal but not changing any state changes that caused React to attempt to re-render. As soon as I did.. boom.

This is outlined pretty succintly by Paul O’Shannessy (one of the React devs) on this issue.

This comment on another issue provides further clarity.

Um.. Semantic-UI-React

At this point you might be punching your monitor noting that various (awesome) contributors have produced Semantic-UI-React - a version of Semantic UI that does not depend on jQuery, and takes the form of a series of Reactive components.

As I mentioned.. I was in a rush (not an excuse), was not thinking, and was also aware of a number of complications pertaining to utilising Semantic-UI-React within our build process. These are discussed here: Shimming dependencies of dependencies when working with Browserify.

Regardless, my perverse scenario/example illustrates nicely as to why React and jQuery do not play nicely.

Also..

My naive attempt to implement the jQuery version of Semantic UIs modal also threw up another issue, namely the positioning within the DOM of the HTML code for my modal.

When at first I realised the problems with my implementation approach I figured that I could simply use Reactive state to add the appropriate CSS classes to my modal containers so as to show/hide them. In principle you can absolutely do this. In the case of modals however there is the additional complexity of having the HTML for your modal external to the containing parent (such that it can be positioned appropriately).

If I simply specify the modal division structure within my React component and then change its CSS classes then it is subject to the styling associated with the parent. Instead I want the modal HTML (DOM structure) external to its parent whilst still allowing it to be controlled/manipulated.

The way that Semantic-UI-React does this is utilising the Portal pattern.

This old StackOverflow answer details a basic implementation of this.

Once again in an attempt to do things quickly I encountered simple issues that would have been patently apparent had I taken a moment prior to putting metaphorical 'pen to paper'.

Hopefully this provides a little clarity, and prevents you from wasting time when working with React and third party libraries.