diff --git a/examples/fiber/index.html b/examples/fiber/index.html index c90e7ce246ed1..6603e0cf93e03 100644 --- a/examples/fiber/index.html +++ b/examples/fiber/index.html @@ -19,26 +19,128 @@

Fiber Example

- + diff --git a/src/renderers/dom/fiber/ReactDOMFiber.js b/src/renderers/dom/fiber/ReactDOMFiber.js index b9d184b788fc1..5734d9039d5cf 100644 --- a/src/renderers/dom/fiber/ReactDOMFiber.js +++ b/src/renderers/dom/fiber/ReactDOMFiber.js @@ -18,6 +18,8 @@ var ReactFiberReconciler = require('ReactFiberReconciler'); var warning = require('warning'); +type Element = HTMLElement; + type DOMContainerElement = Element & { _reactRootContainer: ?Object }; type Container = Element; @@ -41,19 +43,63 @@ function recursivelyAppendChildren(parent : Element, child : HostChildren) : void { + if (container.firstChild === children && container.lastChild === children) { + // Rudimentary bail out mechanism. + return; + } container.innerHTML = ''; recursivelyAppendChildren(container, children); }, createInstance(type : string, props : Props, children : HostChildren) : Instance { const domElement = document.createElement(type); - recursivelyAppendChildren(domElement, children); + if (typeof props.style === 'object') { + Object.assign(domElement.style, props.style); + } + if (typeof props.onMouseEnter === 'function') { + domElement.addEventListener('mouseenter', props.onMouseEnter); + } + if (typeof props.onMouseLeave === 'function') { + domElement.addEventListener('mouseleave', props.onMouseLeave); + } if (typeof props.children === 'string') { domElement.textContent = props.children; + return domElement; } + domElement.innerHTML = ''; + recursivelyAppendChildren(domElement, children); return domElement; }, @@ -63,15 +109,44 @@ var DOMRenderer = ReactFiberReconciler({ newProps : Props, children : HostChildren ) : boolean { + /* + Visualize the reconciliation + */ + if (VISUALIZE_RECONCILIATION && typeof newProps.children === 'string') { + var c = +newProps.children; + if (!isNaN(c)) { + domElement.style.background = COLORS[c]; + } + } return true; }, + beginUpdate(domElement) { + if (VISUALIZE_RECONCILIATION) { + var c = (Math.round(Date.now() / 50) + 2) % COLORS.length; + if (!isNaN(c)) { + domElement.style.border = '3px solid ' + COLORS[c]; + } + } + }, + commitUpdate(domElement : Instance, oldProps : Props, newProps : Props, children : HostChildren) : void { - domElement.innerHTML = ''; - recursivelyAppendChildren(domElement, children); if (typeof newProps.children === 'string') { domElement.textContent = newProps.children; + return; + } + if (typeof newProps.style === 'object') { + Object.assign(domElement.style, newProps.style); + } + if (children && (domElement.firstChild === children || domElement.firstChild === (children : any).output)) { + // Rudimentary bail out mechanism. + return; } + if (domElement.firstChild) { + return; + } + domElement.innerHTML = ''; + recursivelyAppendChildren(domElement, children); }, deleteInstance(instance : Instance) : void { @@ -95,12 +170,14 @@ function warnAboutUnstableUse() { warned = true; } +var rootContainer = null; + var ReactDOM = { render(element : ReactElement, container : DOMContainerElement) { warnAboutUnstableUse(); if (!container._reactRootContainer) { - container._reactRootContainer = DOMRenderer.mountContainer(element, container); + container._reactRootContainer = rootContainer = DOMRenderer.mountContainer(element, container); } else { DOMRenderer.updateContainer(element, container._reactRootContainer); } @@ -117,6 +194,42 @@ var ReactDOM = { } }, + // Logs the current state of the tree. + dumpTree() { + if (!rootContainer) { + console.log('Nothing rendered yet.'); + return; + } + + function logFiber(fiber : any, depth) { + console.log( + ' '.repeat(depth) + '- ' + (fiber.type ? fiber.type.name || fiber.type : '[root]'), + '[' + fiber.pendingWorkPriority + (fiber.pendingProps ? '*' : '') + ']' + ); + const childInProgress = fiber.childInProgress; + if (childInProgress) { + if (childInProgress === fiber.child) { + console.log(' '.repeat(depth + 1) + 'ERROR: IN PROGRESS == CURRENT'); + } else { + console.log(' '.repeat(depth + 1) + 'IN PROGRESS'); + logFiber(childInProgress, depth + 1); + if (fiber.child) { + console.log(' '.repeat(depth + 1) + 'CURRENT'); + } + } + } + if (fiber.child) { + logFiber(fiber.child, depth + 1); + } + if (fiber.sibling) { + logFiber(fiber.sibling, depth); + } + } + + console.log('FIBERS:'); + logFiber((rootContainer.stateNode : any).current, 0); + }, + }; module.exports = ReactDOM;