Kostiantyn Synyshyn
JS engineer
Viscera of React
What is React?
From components to elementsΒ
The problem
The solution
"A JavaScript library for building user interfaces"
import React from 'react'
import ReactDom from 'react-dom'
import { Pressable } from 'react-native'
function Greetings(){
return [
<StyledHeader color="rebeccapurple">
Hello from functional component
</StyledHeader>
<div>
<span>I will be a text node soon π</span>
</div>
]
}
return [
React.createElement(
/* type */ StyledHeader,
/* props */ { color: 'rebeccapurple' },
/* children */ 'Hello from functional component'),
React.createElement(
'div',
null,
React.createElement(
'span',
null,
'I will be a text node soon π'))
]
=
{
type: StyledHeader,
props: {
color: 'rebeccapurple',
children: 'Hello from functional component',
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element')
},
{
type: 'div',
props: {
children: {
{
type: 'span',
props: {
children: 'I will be a text node soon π'
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element')
}
},
},
key: null,
ref: null,
$$typeof: Symbol.for('react.element')
}
$$typeof: 0xeac7
Transformation
Abstraction
Composition
State
Memoization
Lists
Continuations
State map
Memoization map
Algebraic effects
v = fn(data)
function fib(n) {
if (n < 2) return n;
return fib(n - 1) + fib (n - 2);
}
console.log(fib(3));
function a(){
console.log("I do not have access to b's exec context");
b();
};
function b(){
console.log("I have an access to a's exec context");
}
Assign priority to different types of work
Pause work and come back to it later
Abort work if itβs no longer needed
Reuse previously completed work
Components tree you've written using JSX
Elements react created after calling render
Corresponding fiber nodes
We are callable( )
We are IMMUTABLE
We are mutable
function Counter() {
const [count, setCount] = React.useState(0);
const isVisible = count < 2;
return [
<button key="0" onClick={() => setCount(count + 1)}>Increment</button>,
<span key="1">{count}</span>,
{isVisible && <span key="2">Make me disappear</span>}
]
const container = document.querySelector('#app');
ReactDOM.render(<Counter/>, container);
https://codesandbox.io/s/for-lulz-e61kr?file=/src/App.js
function Counter() {
const [count, setCount] = React.useState(0);
const isVisible = count < 2;
return [
<button key="0" onClick={() => setCount(count + 1)}>Increment</button>,
<span key="1">{count}</span>,
{isVisible && <span key="2">Make me disappear</span>}
]
...
return [
React.createElement(
'button',
{
key: '0',
onClick: () => setCount(count+1)
},
'Increment'
),
React.createElement(
'span',
{
key="1"
},
count
),
React.createElement(
'span',
{
key="2"
},
'Make me disappear'
)]
{
$$typeof: Symbol(react.element),
type: 'button',
props: {
key: '0'
children: 'Increment',
onClick: () => { ... }
}
},
{
$$typeof: Symbol(react.element),
type: 'span',
props: {
key: '1'
children: 0
}
},
{
$$typeof: Symbol(react.element),
type: 'span',
props: {
key: '2'
children: 'Make me disappear'
}
}
Host Root
Counter
child
return
child
return
Button
Span
Span
sibling
{
stateNode: Counter(),
type: Counter,
alternate: null,
key: null,
updateQueue: null,
memoizedState: {count: 0},
pendingProps: {},
memoizedProps: {},
tag: 0,
effectTag: 0,
nextEffect: null
}
{
stateNode: new HTMLSpanElement,
type: "span",
alternate: null,
key: null,
updateQueue: null,
memoizedState: null,
pendingProps: {children: 0},
memoizedProps: {children: 0},
tag: 5,
effectTag: 0,
nextEffect: null
}
{
stateNode: new HTMLSpanElement,
type: "span",
alternate: null,
key: null,
updateQueue: null,
memoizedState: null,
pendingProps: {children: 'Make me disappear'},
memoizedProps: {children: 'Make me disappear'},
tag: 5,
effectTag: 0,
nextEffect: null
}
// each of shown fiber
// nodes has following properties
{
child: []
return:
sibling:
}
Host Root
Counter
Button
Span
Span
<span> 2 </span>
<span>Make me...</span>
Host Root
Counter
Button
Span
Span
<span> 3 </span>
<span>Make me...</span>
Host Root
Counter
Button
Span
<span> 3 </span>
<span>Make me...</span>
<span>Make me...</span>
<span>Make me...</span>
<span>Make me...</span>
<span>Make me...</span>
Current
Host Root
Counter
Button
Span
Span
+1
update queue
Current
Work in progress
Host Root
Host Root
Counter
Button
Span
Span
+1
update queue
copy
Current
Work in progress
Host Root
Host Root
Counter
Button
Span
Span
+1
update queue
Counter
+1
update queue
copy
Current
Work in progress
Host Root
Host Root
Counter
Button
Span
Span
+1
update queue
Counter
Button
Span
Span
nextEffect
firstEffect
nextEffect
[UNSAFE_]componentWillMount (deprecated)
[UNSAFE_]componentWillReceiveProps (deprecated)
getDerivedStateFromProps
shouldComponentUpdate
[UNSAFE_]componentWillUpdate (deprecated)
render
Render/ reconcile phase
getSnapshotBeforeUpdate
componentDidMount
componentDidUpdate
componentWillUnmount
Commit phase
Thank you!
Q&A
By Kostiantyn Synyshyn
How React works under the hood