Building custom renderers with React
@satya164
Custom Renderer
An alternative target for rendering React components
3
@satya164
4
@satya164
React DOM
React Native
React
Browser
Mobile
Custom renderers in the wild
5
@satya164
6
@satya164
7
@satya164
8
@satya164
Why?
Same declarative, component based API to build everything
9
@satya164
Fiber
10
@satya164
What’s Fiber?
The new reconciliation algorithm in React 16, based on data structure of the same name used internally.
11
@satya164
Reconciliation
The algorithm used to diff one tree with another to determine which parts need to be changed
12
@satya164
The Canvas API
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, 100, 100);
ctx.fillStyle = 'white';
ctx.font = '14px sans-serif';
ctx.fillText('Hello world', 0, 14);
13
@satya164
What will we build
const App = () => (
<rectangle style={{ height: 100, width: 100 }}>
Hello world!
</rectangle>
);
render(<App />, document.getElementById('canvas'));
14
@satya164
15
@satya164
Let’s build it
16
@satya164
17
@satya164
document
body
a
head
p
text
div
span
page
Building blocks
18
@satya164
Container
Rectangle
Rectangle
Rectangle
Rectangle
Nodes and React elements
// a react element
const element = <div />
// underlying DOM node (HTMLDivElement)
const node = ReactDOM.findDOMNode(element)
19
@satya164
The Container class
// src/Container.js
class Container {
// list of children, e.g. instances of Rectangle
children: [],
// some methods to modify children array
appendChild, removeChild, insertBefore,
// method to redraw the canvas
invalidate,
}
20
@satya164
The Rectangle class
// src/Rectangle.js
class Rectangle {
// list of children, e.g. - strings
children: [],
// some methods to modify children array
appendInitialChild, appendChild, removeChild, insertBefore,
// method to update rectangle properties
replaceProps,
// method to draw the rectangle
draw,
}
21
@satya164
Public API
// src/index.js
export function render(element, canvas) {
const container = CanvasRenderer.createContainer(
new Container(canvas)
);
CanvasRenderer.updateContainer(element, container, null);
}
22
@satya164
CanvasRenderer
23
@satya164
react-reconciler
// src/CanvasRenderer.js
import Reconciler from 'react-reconciler';
const CanvasRenderer = Reconciler({
// hostConfig
});
24
@satya164
The hostConfig object
25
@satya164
26
@satya164
createInstance
createTextInstance
appendInitialChild
createInstance
// src/CanvasRenderer.js
createInstance(type, props) {
switch (type) {
case 'rectangle':
return new Rectangle(props);
default:
throw new Error(`Invalid component type: ${type}`);
}
}
27
@satya164
createTextInstance
// src/CanvasRenderer.js
createTextInstance(text) {
return text;
}
28
@satya164
appendInitialChild
// src/CanvasRenderer.js
appendInitialChild(parentInstance, child) {
parentInstance.appendInitialChild(child);
}
29
@satya164
mutation
30
@satya164
appendChildToContainer
Append a new child to the container instance
31
@satya164
container
0
1
2
3
new child
insertInContainerBefore
Prepend a new child before another in the container instance
32
@satya164
container
0
1
2
3
new child
removeChildFromContainer
Remove a child from the container instance
33
@satya164
container
0
1
2
4
3
appendChild
Append a new child to a rectangle instance
34
@satya164
rectangle
0
1
2
3
new text
insertBefore
Prepend a new child before another child in a rectangle instance
35
@satya164
rectangle
0
1
2
3
new text
removeChild
Remove a child from the a rectangle instance
36
@satya164
rectangle
0
1
2
4
3
commitUpdate
Update the properties of a rectangle instance
37
@satya164
old tree
new tree
commitUpdate
new props
It’s demo time
38
@satya164
Integration with devtools
// src/index.js
CanvasRenderer.injectIntoDevTools({
bundleType: 1, // 0 for PROD, 1 for DEV
version: '0.1.0', // version for the renderer
rendererPackageName: 'canvas-renderer', // package name
findHostInstanceByFiber: CanvasRenderer.findHostInstance, // host instance (root)
});
39
@satya164
40
@satya164
Final implementation
41
@satya164
Resources
42
@satya164
Thank you
Any questions?
43
@satya164