Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using JQuery plugins that transform the DOM in React Components?

Some JQuery plugins don't just add behavior to DOM nodes, but change them. For example, Bootstrap Switch turns

<input type="checkbox" name="my-checkbox" checked>

into something like

<div class="bootstrap-switch bootstrap-switch-wrapper bootstrap-switch-on bootstrap-switch-large bootstrap-switch-animate">   <div class="bootstrap-switch-container">     <span class="bootstrap-switch-handle-on bootstrap-switch-primary">ON</span>     <label class="bootstrap-switch-label">&nbsp;</label>     <span class="bootstrap-switch-handle-off bootstrap-switch-default">OFF</span>     <input type="checkbox" name="download-version" checked="" data-size="large" data-on-text="3" data-off-text="2.0.1">   </div> </div> 

with

$("[name='my-checkbox']").bootstrapSwitch();

Which doesn't jive with React:

Uncaught Error: Invariant Violation: findComponentRoot(..., .0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a <tbody> when using tables or nesting <p> or <a> tags. ...<omitted>...`.  

Is there a recommended technique for incorporating these plugins into React components? Or do they fundamentally break the assumptions of React and cannot work with it?

like image 501
tnunamak Avatar asked Aug 21 '14 21:08

tnunamak


People also ask

Can I use jQuery plugin in React?

We will learn how to import the plugin and use it inside a React component. The first thing to do is to install the jQuery package using npm. Next go to jCirclize's Github repository and download the ZIP file. On completion of download, extract/unzip the ZIP file, copy the files jCirclize.

How use jQuery function in react JS?

Our jQuery app initially creates the React component using a call to React. createElement and passing in the context of the jQuery app to the components constructor. The component can then store the reference (available via the props argument) in its state and use it to update key elements on the web page.

How do I add plugins to React?

If you install the "react-datepicker" package using npm i react-datepicker, the package will be downloaded to he node_modules folder of the project. You can then, import the react-datepicker and use in the files. require is not installed then. Try installing it using, npm i require.


2 Answers

No, react will react (haha) badly to anything that modifies its own component dom structure outside of react. This is something you don't ever want to do. The recommended solution would be to replicate the functionality of whatever you're trying to do with a jquery or similar plugin, in react.

Having said that, there is a reasonable way to do this for specific instances where you just can't do without it, but it essentially means wrapping some non-react dom inside react.

Example:

var Example = React.createClass({     componentDidMount: function() {         var $checkboxContainer = $(this.refs.checkboxContainer.getDOMNode());          var $checkbox = $('<input />').prop('type', 'checkbox');          $checkboxContainer.append($checkbox);          $checkbox.bootstrapSwitch({});     },     render: function() {         return (             <div>                 <div ref="checkboxContainer"></div>             </div>         )     } }); 

Now of course you are rendering a component with a nested div. The nested when mounted to the dom for the first time that nested div will get a checkbox appended to it by jquery, which will then also execute our jquery plugin on it.

This particular example component has little point to it, however you can see how this might integrate into a more complex component while still allowing you to re-render and react to state changes etc. You just lose the ability to directly react to events/modify things inside of the checkbox in question which as far as react is concerned, doesn't exist.

Now with the above example if you were to have some react logic to add/remove the nested div, you'd have to have the same logic around that div being inserted be responsible for re-inserting the checkbox and re-initializing it with the jquery plugin. However because react only modifies the dom when needed, this inserted dom content wont be removed unless you do something that modifies the container div in a way that causes it to be removed/re-rendered to the dom. This means you can still access all of the events within react for that container div etc.

You could also make use of the componentDidMount function in react to bind events or callbacks to specific interactions on the checkbox itself. Just make sure to unbind them correctly in componentWillUnmount or wherever it makes sense to do so in the component lifecycle in your specific case.

like image 61
Mike Driver Avatar answered Sep 19 '22 21:09

Mike Driver


In this great ryanflorence's tutorial you'll get an idea on how to do this:

Wrapping DOM Libs

Methodology

  1. DOM libs usually manipulate the DOM
  2. React tries to re-render and finds a different DOM than it had last time and freaks out
  3. We hide the DOM manipulation from React by breaking the rendering tree and then reconnecting around the DOM the lib manipulates.
  4. Consumers of our component can stay in React-land.
like image 41
mik01aj Avatar answered Sep 18 '22 21:09

mik01aj