react - render() to dom - boris dinkevich - codemotion milan 2016
TRANSCRIPT
Boris Dinkevich
- React evangelist - Cat aficionado - Co-Author of “The Redux book” - Organiser AngularUP & ReactNext
Co-Founder @ 500Tech
De-JSX
const Todos = () => ( <ul> <li>Stuff</li> </ul>);
const Todos = () => ( React.createElement("ul", null, React.createElement("li", null, "Stuff" ), ); );
Tree & DOM
TodosHeader
“div”
“Welcome”
“h1”
“div”
Todo
“Two”
“li”
“ul”
Todo
“One”
“li”
“div”
“Welcome”
“h1”
“div”
“Two”
“li”
“ul”
“One”
“li”
Our tree Our DOM
App
Tree & DOM
TodosHeader
“div”
“Welcome”
“h1”
“div”
Todo
“Two”
“li”
“ul”
Todo
“One”
“li”
Old New
App
TodosHeader
“div”
“Welcome”
“h1”
“div”
Todo
“Two”
“li”
“ul”
Todo
“Million”
“li”
App
Tree & DOM
TodosHeader
“div”
“Welcome”
“h1”
“div”
Todo
“Two”
“li”
“ul”
Todo
“Million”
“li”
“div”
“Welcome”
“h1”
“div”
“Two”
“li”
“ul”
“One”
“li”
Our tree Our DOM
App
Tree & DOM
TodosHeader
“div”
“Welcome”
“h1”
“div”
Todo
“Two”
“li”
“ul”
Todo
“Million”
“li”
“div”
“Welcome”
“h1”
“div”
“Two”
“li”
“ul”
“Million”
“li”
Our tree Our DOM
App
Introducing BorisJS!1.Call render() to build tree - ”Future Tree”
2.Compare each element to DOM
3.Change when needed
4.Win!
Simple diff
function updateNode(node, value) { if (node.innerText !== value) { node.innerText = value; } }
Introducing BorisJS 2.01.Call render() to build tree
2.Read DOM into temp tree - “Current Tree" 3.Compare each element to temp tree
4.Change when needed
5.Win!
“temp tree”… sounds familiar
Pre cache1. Call render() to build “Future Tree”
2. Compare each element to “Current Tree“
3. Change DOM when needed
4.Save “Future Tree” as “Current Tree” 5. Win!
What about first “Current Tree”?
Introducing BorisJS 3.0Initial Render
1.Call render() to build tree
2.Save as “Current Tree” 3.Create initial DOM
Updates
1.Call render() to build “Future Tree”
2.Compare each element to “Current Tree” 4.Change DOM when needed
5.Save “Future Tree” as “Current Tree”
6.Win!
todos = document.getElementById('app').children[0].children[1]; todos.removeChild(todos.childNodes[0]);
Todos.setState({ todos: [‘XXXXX’, ‘Dos’] });
Todos• Dos
Todos• One • Two
Todos• Two
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
Mounting markup
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
Mounting markup
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
“Welcome”
“h1”
“div”
Mounting markup
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
“Welcome”
“h1”
“div”
Mounting markup
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
“Welcome”
“h1”
“div”
“One”
“li”
Mounting markup
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
“Welcome”
“h1”
“div”
“One”
“li”
Mounting markup
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
“Welcome”
“h1”
“div”
“Two”
“li”
“One”
“li”
Mounting markup
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
“Welcome”
“h1”
“div”
“Two”
“li”
“ul”
“One”
“li”
Mounting markup
function Todos()
function Header()
“div”
“Welcome”
“h1”
“div”
function Todo()
“Two”
“li”
“ul
function Todo()
“One”
“li”
function App()
“Welcome”
“h1”
“div”
“Two”
“li”
“ul”
“One”
“li”
Mounting markup
“div”
“div”
“Welcome”
“h1”
“div”
“Two”
“li”
“ul”
“One”
“li”
#app
markup
<body> <div id="app"></div></body>
render( React.createElement(App), document.getElementById('app') );
What is “React”?
addons 1,334 isomorphic 3,428 shared 7,058
renderers/ art 641 dom 12,337 native 2,735 noop 192 shared 9,368
* lines of code in 15-stable
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“One”
“li”
“div”
“Two”
“li”
“ul”
“One”
“li”
DOMReact Tree prev Virtual DOM
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“One”
“li”
“div”
“Two”
“li”
“ul”
“One”
“li”
DOMReact Tree prev Virtual DOM
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“One”
“li”
“div”
“Two”
“li”
“ul”
“One”
“li”
DOMReact Tree prev Virtual DOM
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“One”
“li”
“div”
“Two”
“li”
“ul”
“One”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“One”
“li”
“div”
“Two”
“li”
“ul”
“One”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“One”
“li”
“div”
“Two”
“li”
“ul”
“One”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“One”
“li”
“div”
“Two”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“Uno”
“li”
“div”
“Two”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“Uno”
“li”
“div”
“Two”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“Uno”
“li”
“div”
“Two”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“Uno”
“li”
“div”
“Two”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Two”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
Flow1. setState({ todos: [‘Uno’, ‘Dos’] });
2. Todos updated and rendering starts
3. Todo1 needs update
4. DOM updated
5. Todo2 needs update
6. DOM updated
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
“div”
“Dos”
“li”
“ul”
“Uno”
“li”
DOMReact Tree prev Virtual DOM
‘UNO’ ‘DOS’
function Todos()
“div”
function Todo()
{ title }
“li”
“ul”
function Todo()
{ title }
“li”
function App()
React Tree
componentWillMount componentDidMount componentWillUpdate componentDidUpdate componentWillUnmount …
Multiple setState calls
Todos.setState({ todos: [‘Uno’, ‘Dos’] }); App.setState({ title: ‘Bye’ }); Todos.setState({ todos: [‘Raz’, ‘Dva’] });
How do we group?
Todos.setState({ todos: [‘Uno’, ‘Dos’] }); App.setState({ title: ‘Bye’ }); Todos.setState({ todos: [‘Raz’, ‘Dva’] });
Callback
Before
After
• Prepare
• Calculate final state • Update DOM • Run Callbacks
Transaction
• multiple setState() • Build list of changes
App
dirtyComponents
Todos.setState({ todos: [‘Uno’, ‘Dos’] }); App.setState({ title: ‘Bye’ });
{ todos: [‘Uno’, ‘Dos’] }
Todos
{ title: ‘Bye’ }
dirtyComponents
Todos.setState({ todos: [‘Uno’, ‘Dos’] }); App.setState({ title: ‘Bye’ }); Todos.setState({ todos: [‘Raz’, ‘Dva’] });
{ todos: [‘Uno’, ‘Dos’] } { todos: [‘Raz’, ‘Dva’] }
Todos
{ title: ‘Bye’ }
App
How many render() ?
App()
Todos()
Todos()
Todo()
App() 0
0
0
Update the state to it’s latest version
Callback order in transaction
Todos.setState({ todos: [‘Uno’, ‘Dos’] }); App.setState({ title: ‘Bye’ }); Todos.setState({ todos: [‘Raz’, ‘Dva’] });
1. App setState 2. Todos setState 3. Todos setState
Callbacks order
Transactions In ReactPreserving input selection
Suppressing events during DOM work
Collecting “componentDidUpdate”
etc