External Reagent Access

I want to make an application using React.js. I want it to be easily customizable from the outside world (for example, by writing user scripts). The idea I was trying to use was to make some special properties in the state of the root element (like sidebarItems or playlistCreatedHooks ) so addon developers could add something there. My questions: this is a good way to do this, is there a right way to achieve something similar to my goal and, finally, how can add-on developers get access to these details?

+6
source share
2 answers

One option is observable. This is basically an object on which you can listen to changes and create changes. You can also fire other events, like adding an event to data.playlists, to create the api you want to provide.

 // data.js var data = { sidebarItems: Observable([]), playlists: Observable([]) }; // app.js var App = React.createComponent({ mixins: [data.sidebarItems.mixin("sidebar")], render: function(){ return this.state.sidebar.map(renderSidebarItem); } }); /// userscript.js // causes the view to update data.sidebarItems.set(somethingElse); // run when someone does data.playlists.set(...) data.playlists.on('change', function(playlists){ }); // an event you could choose to emit with data.playlists.emit('add', newPlaylist) data.playlists.on('add', function(newPlaylist){ }); 

Here's an example of an (untested) implementation of the Observable that was used above, with an extra function to create a mixin reactive component.

 var events = require('events'); // or some other way of getting it var Observable = function(initialValue){ var self = new events.EventEmitter(); var value = initialValue; self.get = function(){ return value }; self.set = function(updated){ value = updated; self.emit('change', updated); }; self.mixin = function(key){ var cbName = Math.random().toString(); var mixin = { getInitialState: function(){ var o = {}; o[key] = value; return o }, componentDidMount: function(){ self.on('change', this[cbName]); }, componentWillUnmount: function(){ self.removeListener('change', this[cbName]); } } mixin[cbName] = function(){ var o = {}; o[key] = value; this.setState(o); }; return mixin; } return self; } 
+8
source

Here is my solution. Thanks to this, the state of Observable the React is automatically updated (with its consequences, for example, with the reprocessing of a component), and you can even listen to changes out of response thanks to the .on method.

 var eventEmitter = { _JQInit: function() { this._JQ = jQuery(this); }, emit: function(evt, data) { !this._JQ && this._JQInit(); this._JQ.trigger(evt, data); }, once: function(evt, handler) { !this._JQ && this._JQInit(); this._JQ.one(evt, handler); }, on: function(evt, handler) { !this._JQ && this._JQInit(); this._JQ.bind(evt, handler); }, off: function(evt, handler) { !this._JQ && this._JQInit(); this._JQ.unbind(evt, handler); } }; var Observable = function(initialValue, name) { var self = eventEmitter; var name = name; var obj = { value: initialValue, ops: self }; self.get = function() { return obj.value }; self.set = function(updated){ if(obj.value == updated) return; obj.value = updated; self.emit('change', updated); }; self.mixin = function() { var mixin = { getInitialState: function() { var obj_ret = {}; obj_ret[name] = obj; return obj_ret; }, componentDidMount : function() { self.on('change', function() { var obj_new = {}; obj_new[name] = obj; this.setState(obj_new); }.bind(this)); } }; return mixin; }; return self; }; 
Example

(using it to display a warning on another component): // Observed init alert_msg = Observed ('', 'alertmsg');

 var ConfirmBtn = React.createClass({ mixins: [alert_msg.mixin()], handleConfirm: function(e) { e.preventDefault(); this.state.alertmsg.ops.set(null); if(! $('#cgv').is(':checked')) { this.state.alertmsg.ops.set('Please accept our terms of conditions'); return; } } } var AlertPayment = React.createClass({ mixins: [alert_msg.mixin()], render: function() { var style = (this.state.alertmsg === null) ? {display: 'none'} : {display: 'block'}; return ( <div style={style} className="alertAcceptTerms"> {this.state.alertmsg.value} </div> ); } }); 

Hope this helps

+1
source

Source: https://habr.com/ru/post/975889/


All Articles