2014-09-26 21 views
6

Desidero creare un'app utilizzando React.js. Voglio che sia facilmente personalizzabile dal mondo esterno (ad esempio scrivendo gli script degli utenti). L'idea che ho tentato di utilizzare è di creare alcune proprietà speciali nello stato dell'elemento radice (come sidebarItems o playlistCreatedHooks) così gli sviluppatori di addon potrebbero aggiungere qualcosa lì. Le mie domande sono: è un buon modo per farlo, c'è il Right Way ™ per raggiungere qualcosa di simile al mio obiettivo e, infine, come potranno gli sviluppatori addon accedere a questi oggetti di scena?Accesso allo stato React dall'esterno

risposta

8

Un'opzione è osservabile. Fondamentalmente è un oggetto su cui puoi ascoltare le modifiche e creare un cambiamento. È anche possibile emettere altri eventi come un evento "aggiungi" su data.playlists per creare l'API che si desidera fornire.

// 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){ 

}); 

Ecco un esempio (non testata) attuazione Osservabile usato sopra, con una funzione aggiuntiva per generare la mixin componente reagire.

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; 
} 
+0

Whoa, sembra impressionante, grazie! – Ale

1

Ecco la mia soluzione. Grazie a questo, lo stato dei componenti Observable the React viene aggiornato automaticamente (con le sue conseguenze, come il re-rendering del componente) e si può anche ascoltare le modifiche esterne reagendo grazie al metodo .on.

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; 
}; 

esempio (usando per mostrare un avviso su un altro componente): // osservabile init alert_msg = Osservabile ('', '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> 
     ); 
    } 
}); 

Speranza che aiuta

Problemi correlati