motion
Version:
motion - moving development forward
147 lines (129 loc) • 4.85 kB
JavaScript
/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMTextComponent
*/
'use strict';
var DOMChildrenOperations = require('./DOMChildrenOperations');
var DOMLazyTree = require('./DOMLazyTree');
var DOMPropertyOperations = require('./DOMPropertyOperations');
var ReactDOMComponentTree = require('./ReactDOMComponentTree');
var ReactPerf = require('./ReactPerf');
var assign = require('./Object.assign');
var escapeTextContentForBrowser = require('./escapeTextContentForBrowser');
var validateDOMNesting = require('./validateDOMNesting');
var getNode = ReactDOMComponentTree.getNodeFromInstance;
/**
* Text nodes violate a couple assumptions that React makes about components:
*
* - When mounting text into the DOM, adjacent text nodes are merged.
* - Text nodes cannot be assigned a React root ID.
*
* This component is used to wrap strings in elements so that they can undergo
* the same reconciliation that is applied to elements.
*
* TODO: Investigate representing React components in the DOM with text nodes.
*
* @class ReactDOMTextComponent
* @extends ReactComponent
* @internal
*/
var ReactDOMTextComponent = function (props) {
// This constructor and its argument is currently used by mocks.
};
assign(ReactDOMTextComponent.prototype, {
/**
* @param {ReactText} text
* @internal
*/
construct: function (text) {
// TODO: This is really a ReactText (ReactNode), not a ReactElement
this._currentElement = text;
this._stringText = '' + text;
// ReactDOMComponentTree uses these:
this._nativeNode = null;
this._nativeParent = null;
// Properties
this._domID = null;
this._mountIndex = 0;
},
/**
* Creates the markup for this text node. This node is not intended to have
* any features besides containing text content.
*
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
* @return {string} Markup for this text node.
* @internal
*/
mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) {
if (process.env.NODE_ENV !== 'production') {
var parentInfo;
if (nativeParent != null) {
parentInfo = nativeParent._ancestorInfo;
} else if (nativeContainerInfo != null) {
parentInfo = nativeContainerInfo._ancestorInfo;
}
if (parentInfo) {
// parentInfo should always be present except for the top-level
// component when server rendering
validateDOMNesting('span', this, parentInfo);
}
}
var domID = nativeContainerInfo._idCounter++;
this._domID = domID;
this._nativeParent = nativeParent;
if (transaction.useCreateElement) {
var ownerDocument = nativeContainerInfo._ownerDocument;
var el = ownerDocument.createElement('span');
ReactDOMComponentTree.precacheNode(this, el);
var lazyTree = DOMLazyTree(el);
DOMLazyTree.queueText(lazyTree, this._stringText);
return lazyTree;
} else {
var escapedText = escapeTextContentForBrowser(this._stringText);
if (transaction.renderToStaticMarkup) {
// Normally we'd wrap this in a `span` for the reasons stated above, but
// since this is a situation where React won't take over (static pages),
// we can simply return the text as it is.
return escapedText;
}
return '<span ' + DOMPropertyOperations.createMarkupForID(domID) + '>' + escapedText + '</span>';
}
},
/**
* Updates this component by updating the text content.
*
* @param {ReactText} nextText The next text content
* @param {ReactReconcileTransaction} transaction
* @internal
*/
receiveComponent: function (nextText, transaction) {
if (nextText !== this._currentElement) {
this._currentElement = nextText;
var nextStringText = '' + nextText;
if (nextStringText !== this._stringText) {
// TODO: Save this as pending props and use performUpdateIfNecessary
// and/or updateComponent to do the actual update for consistency with
// other component types?
this._stringText = nextStringText;
DOMChildrenOperations.updateTextContent(getNode(this), nextStringText);
}
}
},
getNativeNode: function () {
return getNode(this);
},
unmountComponent: function () {
ReactDOMComponentTree.uncacheNode(this);
}
});
ReactPerf.measureMethods(ReactDOMTextComponent.prototype, 'ReactDOMTextComponent', {
mountComponent: 'mountComponent',
receiveComponent: 'receiveComponent'
});
module.exports = ReactDOMTextComponent;