Rudimentary DOM Renderer with Example
Sebastian Markbage committed
Jun 30, 2016 at 14:30 UTC
05c69252821cafaea921dce7fcddae51c0aa3121
2 files changed
+143
examples/fiber/index.html
new
+44
@@ -0,0 +1,44 @@
1
+<!DOCTYPE html>
2
+<html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Fiber Example</title>
6
+ <link rel="stylesheet" href="../shared/css/base.css" />
7
+ </head>
8
+ <body>
9
+ <h1>Fiber Example</h1>
10
+ <div id="container">
11
+ <p>
12
+ To install React, follow the instructions on
13
+ <a href="https://github.com/facebook/react/">GitHub</a>.
14
+ </p>
15
+ <p>
16
+ If you can see this, React is <strong>not</strong> working right.
17
+ If you checked out the source from GitHub make sure to run <code>grunt</code>.
18
+ </p>
19
+ </div>
20
+ <script src="../../build/react.js"></script>
21
+ <script src="../../build/react-dom.js"></script>
22
+ <script>
23
+ function ExampleApplication(props) {
24
+ var elapsed = Math.round(props.elapsed / 100);
25
+ var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0' );
26
+ var message =
27
+ 'React has been successfully running for ' + seconds + ' seconds.';
28
+
29
+ return React.DOM.p(null, message);
30
+ }
31
+
32
+ // Call React.createFactory instead of directly call ExampleApplication({...}) in React.render
33
+ var ExampleApplicationFactory = React.createFactory(ExampleApplication);
34
+
35
+ var start = new Date().getTime();
36
+ setInterval(function() {
37
+ ReactDOM.render(
38
+ ExampleApplicationFactory({elapsed: new Date().getTime() - start}),
39
+ document.getElementById('container')
40
+ );
41
+ }, 50);
42
+ </script>
43
+ </body>
44
+</html>
src/renderers/dom/fiber/ReactDOMFiber.js
new
+99
@@ -0,0 +1,99 @@
1
+/**
2
+ * Copyright 2013-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactDOMFiber
10
+ * @flow
11
+ */
12
+
13
+/**
14
+ * This is a renderer of React that doesn't have a render target output.
15
+ * It is useful to demonstrate the internals of the reconciler in isolation
16
+ * and for testing semantics of reconciliation separate from the host
17
+ * environment.
18
+ */
19
+
20
+'use strict';
21
+
22
+import type { HostChildren } from 'ReactFiberReconciler';
23
+
24
+var ReactFiberReconciler = require('ReactFiberReconciler');
25
+
26
+type DOMContainerElement = Element & { _reactRootContainer: Object };
27
+
28
+type Container = Element;
29
+type Props = { };
30
+type Instance = Element;
31
+
32
+function recursivelyAppendChildren(parent : Element, child : HostChildren<Instance>) {
33
+ if (!child) {
34
+ return;
35
+ }
36
+ /* $FlowFixMe: Element should have this property. */
37
+ if (child.nodeType === 1) {
38
+ /* $FlowFixMe: Refinement issue. I don't know how to express different. */
39
+ parent.appendChild(child);
40
+ } else {
41
+ /* As a result of the refinement issue this type isn't known. */
42
+ let node : any = child;
43
+ do {
44
+ recursivelyAppendChildren(parent, node.output);
45
+ } while (node = node.sibling);
46
+ }
47
+}
48
+
49
+var DOMRenderer = ReactFiberReconciler({
50
+
51
+ updateContainer(container : Container, children : HostChildren<Instance>) : void {
52
+ container.innerHTML = '';
53
+ recursivelyAppendChildren(container, children);
54
+ },
55
+
56
+ createInstance(type : string, props : Props, children : HostChildren<Instance>) : Instance {
57
+ const domElement = document.createElement(type);
58
+ recursivelyAppendChildren(domElement, children);
59
+ if (typeof props.children === 'string') {
60
+ domElement.textContent = props.children;
61
+ }
62
+ return domElement;
63
+ },
64
+
65
+ prepareUpdate(domElement : Instance, oldProps : Props, newProps : Props, children : HostChildren<Instance>) : boolean {
66
+ return true;
67
+ },
68
+
69
+ commitUpdate(domElement : Instance, oldProps : Props, newProps : Props, children : HostChildren<Instance>) : void {
70
+ domElement.innerHTML = '';
71
+ recursivelyAppendChildren(domElement, children);
72
+ if (typeof newProps.children === 'string') {
73
+ domElement.textContent = newProps.children;
74
+ }
75
+ },
76
+
77
+ deleteInstance(instance : Instance) : void {
78
+ // Noop
79
+ },
80
+
81
+ scheduleHighPriCallback: window.requestAnimationFrame,
82
+
83
+ scheduleLowPriCallback: window.requestIdleCallback,
84
+
85
+});
86
+
87
+var ReactDOM = {
88
+
89
+ render(element : ReactElement<any>, container : DOMContainerElement) {
90
+ if (!container._reactRootContainer) {
91
+ container._reactRootContainer = DOMRenderer.mountContainer(element, container);
92
+ } else {
93
+ DOMRenderer.updateContainer(element, container._reactRootContainer);
94
+ }
95
+ },
96
+
97
+};
98
+
99
+module.exports = ReactDOM;