i have seen couple of examples in google of them seems outdated. idea how can use jquery ui react?
if really need that, here approach using.
the plan: create component manage jquery plugin. component provide react-centric view of jquery component. moreover, will:
- use react lifecycle methods initialize , tear down jquery plugin;
- use react
props
plugin configuration options , hook plugin's methods events; - destroy plugin when component unmounts.
let's explore practical example how jquery ui sortable plugin.
tldr: final version
if want grab final version of wrapped jquery ui sortable example:
- here gist made full annotated comments;
- and here's jsfiddle demo, full annotated comments too;
... plus, below the shortened longer comments code snippet:
class sortable extends react.component { componentdidmount() { this.$node = $(this.refs.sortable); this.$node.sortable({ opacity: this.props.opacity, change: (event, ui) => this.props.onchange(event, ui) }); } shouldcomponentupdate() { return false; } componentwillreceiveprops(nextprops) { if (nextprops.enable !== this.props.enable) this.$node.sortable(nextprops.enable ? 'enable' : 'disable'); } renderitems() { return this.props.data.map( (item, i) => <li key={i} classname="ui-state-default"> <span classname="ui-icon ui-icon-arrowthick-2-n-s"></span> { item } </li> ); } render() { return ( <ul ref="sortable"> { this.renderitems() } </ul> ); } componentwillunmount() { this.$node.sortable('destroy'); } };
optionally, can set default props (in case of none passed) , prop types:
sortable.defaultprops = { opacity: 1, enable: true }; sortable.proptypes = { opacity: react.proptypes.number, enable: react.proptypes.bool, onchange: react.proptypes.func.isrequired };
... , here's how use <sortable />
component:
class mycomponent extends react.component { constructor(props) { super(props); // use flag disable/enable <sortable /> this.state = { isenabled: true }; this.toggleenableability = this.toggleenableability.bind(this); } toggleenableability() { this.setstate({ isenabled: ! this.state.isenabled }); } handleonchange(event, ui) { console.log('dom changed!', event, ui); } render() { const list = ['reactjs', 'jsx', 'javascript', 'jquery', 'jquery ui']; return ( <div> <button type="button" onclick={this.toggleenableability}> toggle enable/disable </button> <sortable opacity={0.8} data={list} enable={this.state.isenabled} onchange={this.handleonchange} /> </div> ); } } reactdom.render(<mycomponent />, document.getelementbyid('app'));
the full explanation
for of you, want understand why , how. here's step step guide:
step 1: create component.
our component accept array (list) of items (strings) data
prop.
class sortable extends react.component { componentdidmount() { // every react component has function exposes // underlying dom node wrapping. can use // dom node, pass jquery , initialize plugin. // you'll find many jquery plugins follow same pattern // , you'll able pass component dom node jquery // , call plugin function. // dom node , store jquery element reference this.$node = $(this.refs.sortable); // initialize jquery ui functionality need // in case, sortable: https://jqueryui.com/sortable/ this.$node.sortable(); } // jquery ui sortable expects <ul> list <li>s. renderitems() { return this.props.data.map( (item, i) => <li key={i} classname="ui-state-default"> <span classname="ui-icon ui-icon-arrowthick-2-n-s"></span> { item } </li> ); } render() { return ( <ul ref="sortable"> { this.renderitems() } </ul> ); } };
step 2: pass configuration options via props
let's want configure the opacity of helper while sorting. we'll use opacity
option in plugin configuration, takes values 0.01
1
.
class sortable extends react.component { // ... omitted brevity componentdidmount() { this.$node = $(this.refs.sortable); this.$node.sortable({ // incoming `opacity` prop , use in plugin configuration opacity: this.props.opacity, }); } // ... omitted brevity }; // optional: set default props, in case none passed sortable.defaultprops = { opacity: 1 };
and here's how can use component in our code now:
<sortable opacity={0.8} />
the same way, can map of jquery ui sortable options.
step 3: hook-up functions on plugin events.
you need hook-up on of plugin methods, in order perform react logic, example, manipulate state let's day.
here's how that:
class sortable extends react.component { // ... omitted brevity componentdidmount() { this.$node = $(this.refs.sortable); this.$node.sortable({ opacity: this.props.opacity, // incoming onchange function // , invoke on sortable `change` event change: (event, ui) => this.props.onchange(event, ui) }); } // ... omitted brevity }; // optional: set prop types sortable.proptypes = { onchange: react.proptypes.func.isrequired };
and here's how use it:
<sortable opacity={0.8} onchange={ (event, ui) => console.log('dom changed!', event, ui) } />
step 4: pass future updates control jquery
right after reactjs adds element in actual dom, need pass future control jquery. otherwise, reactjs never re-render our component, don't want that. want jquery responsible updates.
react lifecycle methods comes rescue!
use shouldcomponentupdate() let react know if component's output not affected current change in state or props. default behavior re-render on every state change, , in vast majority, don't want behavior!
shouldcomponentupdate()
invoked before rendering when new props or state being received. if shouldcomponentupdate()
returns false
, componentwillupdate()
, render()
, , componentdidupdate()
not invoked.
then, use componentwillreceiveprops()
, compare this.props
nextprops
, call jquery ui sortable updates when necessary. example, implement enable/disable option of jquery ui sortable.
class sortable extends react.component { // force single-render of component, // returning false shouldcomponentupdate reactjs lifecycle hook. // right after reactjs adds element in actual dom, // need pass future control jquery. // way, reactjs never re-render our component, // , jquery responsible updates. shouldcomponentupdate() { return false; } componentwillreceiveprops(nextprops) { // each time when component receives new props, // should trigger refresh or perform else need. // example, we'll update enable/disable option, // receive different value this.props.enable if (nextprops.enable !== this.props.enable) { this.$node.sortable(nextprops.enable ? 'enable' : 'disable'); } } // ... omitted brevity }; // optional: set default props, in case none passed sortable.defaultprops = { enable: true }; // optional: set prop types sortable.proptypes = { enable: react.proptypes.bool };
step 5: clean mess.
many jquery plugins provide mechanism cleaning after when no longer needed. jquery ui sortable provides event can trigger tell plugin unbind dom events , destroy. react lifecycle methods comes rescue again , provides mechanism hook when component being unmounted.
class sortable extends react.component { // ... omitted brevity componentwillunmount() { // clean mess when component unmounts this.$node.sortable('destroy'); } // ... omitted brevity };
conclusion
wrapping jquery plugins react not best choice. however, nice know option , how can implement solution. viable option if migrating legacy jquery application react or maybe can't find react plugin suits needs in case.
in case library modifies dom, try keep react out of way. react works best when has full control of dom. in these cases, react components more of wrappers 3rd party libraries. using componentdidmount/componentwillunmount initialize/destroy third party library. , props way of giving parent way of customizing behavior of third party library child wraps , hook-up on plugin events.
you can use approach integrate jquery plugin!
Comments
Post a Comment