golden-layout
Version:
A multi-screen javascript Layout manager https://golden-layout.com
102 lines (92 loc) • 3.01 kB
JavaScript
/**
* A specialised GoldenLayout component that binds GoldenLayout container
* lifecycle events to react components
*
* @constructor
*
* @param {lm.container.ItemContainer} container
* @param {Object} state state is not required for react components
*/
lm.utils.ReactComponentHandler = function( container, state ) {
this._reactComponent = null;
this._originalComponentWillUpdate = null;
this._container = container;
this._initialState = state;
this._reactClass = this._getReactClass();
this._container.on( 'open', this._render, this );
this._container.on( 'destroy', this._destroy, this );
};
lm.utils.copy( lm.utils.ReactComponentHandler.prototype, {
/**
* Creates the react class and component and hydrates it with
* the initial state - if one is present
*
* By default, react's getInitialState will be used
*
* @private
* @returns {void}
*/
_render: function() {
this._reactComponent = ReactDOM.render( this._getReactComponent(), this._container.getElement()[ 0 ]);
this._originalComponentWillUpdate = this._reactComponent.componentWillUpdate || function(){};
this._reactComponent.componentWillUpdate = this._onUpdate.bind( this );
if( this._container.getState() ) {
this._reactComponent.setState( this._container.getState() );
}
},
/**
* Removes the component from the DOM and thus invokes React's unmount lifecycle
*
* @private
* @returns {void}
*/
_destroy: function() {
ReactDOM.unmountComponentAtNode( this._container.getElement()[ 0 ]);
this._container.off( 'open', this._render, this );
this._container.off( 'destroy', this._destroy, this );
},
/**
* Hooks into React's state management and applies the componentstate
* to GoldenLayout
*
* @private
* @returns {void}
*/
_onUpdate: function( nextProps, nextState ) {
this._container.setState( nextState );
this._originalComponentWillUpdate.call( this._reactComponent, nextProps, nextState );
},
/**
* Retrieves the react class from GoldenLayout's registry
*
* @private
* @returns {React.Class}
*/
_getReactClass: function() {
var componentName = this._container._config.component;
var reactClass;
if( !componentName ) {
throw new Error( 'No react component name. type: react-component needs a field `component`' );
}
reactClass = this._container.layoutManager.getComponent( componentName );
if( !reactClass ) {
throw new Error( 'React component "' + componentName + '" not found. ' +
'Please register all components with GoldenLayout using `registerComponent(name, component)`' );
}
return reactClass;
},
/**
* Copies and extends the properties array and returns the React element
*
* @private
* @returns {React.Element}
*/
_getReactComponent: function() {
var defaultProps = {
glEventHub: this._container.layoutManager.eventHub,
glContainer: this._container,
};
var props = $.extend( defaultProps, this._container._config.props );
return React.createElement( this._reactClass, props );
}
});