Upgrade to Pro — share decks privately, control downloads, hide ads and more …

🇮🇱 React Next 2022

🇮🇱 React Next 2022

ℹ️ Inside Fiber: the in-depth overview you wanted a TLDR for

We'll have an in-depth overview of the important concepts behind reconciliation and React Fiber. Then, we'll explore how React uses this algorithm and go through a few magic words we hear a lot, like coroutines, continuations, generators, and algebraic effects—and see how they all relate to React.

Matheus Albuquerque

June 28, 2022
Tweet

More Decks by Matheus Albuquerque

Other Decks in Technology

Transcript

  1. Hello, React Next 🙋 🇮🇱 🌎
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR • THE 28TH OF JUNE, 2022.

    View full-size slide

  2. MATHEUS ALBUQUERQUE
    INSIDE FIBER
    THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  3. I’M MATHEUS 🙋
    ↝ @YTHECOMBINATOR ON THE WEB


    ↝ SR. SOFTWARE ENGINEER @ MEDALLIA


    ↝ MENTOR @ TECHLABS BERLIN

    View full-size slide

  4. ⚠ DISCLAIMER ⚠

    View full-size slide

  5. 1. REACT SOURCE CODE IS
    CONSTANTLY CHANGING, AND
    SOME THOUGHTS ARE
    SPECULATIVE

    View full-size slide

  6. 2. MAYBE THIS TALK WON’T BE 100%
    WHAT YOU’D CALL A TLDR

    View full-size slide

  7. 2. MAYBE THIS TALK WON’T BE 100%
    WHAT YOU’D CALL A TLDR
    🤯= HUGE CONTENT
    PAYLOAD / DESERVES
    FURTHER DISCUSSIONS
    AFTER THE SESSION

    View full-size slide

  8. A bit of context
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  9. HTTPS://GITHUB.COM/


    MACABEUS/JS-PROPOSAL-ALGEBRAIC-EFFECTS

    View full-size slide

  10. CONTINUATIONS
    ALGEBRAIC EFFECTS
    COROUTINES
    FIBERS
    THREADS
    GENERATORS

    View full-size slide

  11. ALGEBRAIC EFFECTS
    COROUTINES
    FIBERS
    GENERATORS
    CONTINUATIONS
    THREADS

    View full-size slide

  12. Fiber(s)
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  13. function add(x,y) {


    const result
    =
    x + y;


    return result;


    }


    add(2, 2)

    View full-size slide

  14. let frame: Frame
    =
    {


    return: frame,


    fn: add,


    parameters: [2, 2],


    localVariables: {


    result: 4,


    },


    }

    View full-size slide

  15. let frame: Frame
    =
    {


    return: frame,


    fn: add,


    parameters: [2, 2],


    localVariables: {


    result: 4,


    },


    }
    let fiber: Fiber
    =
    {


    return: fiber,


    component: Avatar,


    props: { id: 4 },


    state: {


    isLoaded: true,


    },


    }

    View full-size slide

  16. ↝ FIBER ARCHITECTURE ⇢ REACT-SPECIFIC
    IMPLEMENTATION OF A CALL-STACK-LIKE MODEL
    WHERE REACT HAS FULL CONTROL OF SCHEDULING
    WHAT SHOULD BE DONE


    ↝ FIBER ⇢ A STACK FRAME FOR A REACT COMPONENT

    View full-size slide

  17. Fibers as


    Units of Work
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  18. DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE
    TREE OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE
    FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.
    ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END
    UP WITH A BUNCH OF REACT ELEMENTS.

    View full-size slide

  19. DURING RECONCILIATION, DATA FROM EVERY REACT
    ELEMENT RETURNED FROM THE RENDER METHOD IS
    MERGED INTO THE TREE OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE
    FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.
    ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END
    UP WITH A BUNCH OF REACT ELEMENTS.

    View full-size slide

  20. DEPENDING ON THE TYPE OF A REACT ELEMENT THE
    FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.
    ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END
    UP WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE
    TREE OF FIBER NODES.

    View full-size slide

  21. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.
    ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END
    UP WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE
    TREE OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE
    FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES.

    View full-size slide

  22. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END
    UP WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE
    TREE OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE
    FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    A UNIT OF WORK.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.

    View full-size slide

  23. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END
    UP WITH A BUNCH OF REACT ELEMENTS.
    DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT
    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE
    TREE OF FIBER NODES.
    DEPENDING ON THE TYPE OF A REACT ELEMENT THE
    FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES.
    A UNIT OF WORK.
    EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT
    DESCRIBES THE WORK THAT NEEDS TO BE DONE.
    AND THAT MAKES IT A
    CONVENIENT WAY TO TRACK,
    SCHEDULE, PAUSE AND
    ABORT THE WORK.

    View full-size slide

  24. Visualizing


    Units of Work
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  25. 🤓💻
    EXPERIMENT #1


    INSPECTING ELEMENTS

    View full-size slide

  26. let fiberNode
    =
    fiberRoot.current;


    let fibersMap
    =
    new Map();


    while (fiberNode) {


    if (fiberNode.stateNode
    !
    =
    =
    null) {


    fibersMap.set(fiberNode.stateNode, fiberNode);


    }


    if (fiberNode.child === null) {


    while (fiberNode
    !
    =
    =
    null
    &
    &
    fiberNode.sibling === null) {


    fiberNode
    =
    fiberNode.return;


    }


    fiberNode
    =
    fiberNode?.sibling;


    continue;


    }


    fiberNode
    =
    fiberNode.child;


    }

    View full-size slide

  27. let fiberNode
    =
    fiberRoot.current;


    let fibersMap
    =
    new Map();


    while (fiberNode) {


    if (fiberNode.stateNode
    !
    =
    =
    null) {


    fibersMap.set(fiberNode.stateNode, fiberNode);


    }


    if (fiberNode.child === null) {


    while (fiberNode
    !
    =
    =
    null
    &
    &
    fiberNode.sibling === null) {


    fiberNode
    =
    fiberNode.return;


    }


    fiberNode
    =
    fiberNode?.sibling;


    continue;


    }


    fiberNode
    =
    fiberNode.child;


    }
    🤯

    View full-size slide

  28. HTTPS://YOUTU.BE/ZCUYPIUIONS
    HTTPS://GITHUB.COM/FACEBOOK/REACT/BLOB/MAIN/


    PACKAGES/REACT-RECONCILER/SRC/REACTINTERNALTYPES.JS

    View full-size slide

  29. HTTPS://YOUTU.BE/ZCUYPIUIONS
    HTTPS://GITHUB.COM/FACEBOOK/REACT/BLOB/MAIN/


    PACKAGES/REACT-RECONCILER/SRC/REACTWORKTAGS.JS

    View full-size slide

  30. Manipulating
    Units of Work
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  31. 🙋✋
    QUESTION #1


    HAVE YOU EVER HEARD ABOUT HOMOICONICITY?

    View full-size slide

  32. (let [x 1]


    (inc x)) ;
    =
    >
    2

    View full-size slide

  33. PERFORMS A TEMPORARY BINDING


    (BINDS X TO THE VALUE 1)
    (let [x 1]


    (inc x)) ;
    =
    >
    2

    View full-size slide

  34. INCREMENTS X TO GIVE THE
    RETURN VALUE OF 2
    (let [x 1]


    (inc x)) ;
    =
    >
    2

    View full-size slide

  35. IT CAN BE THOUGHT OF AS A LIST WITH THREE ELEMENTS


    ↝ A SYMBOL NAMED LET


    ↝ A VECTOR WITH TWO ELEMENTS


    ↝ A SYMBOL NAMED X


    ↝ AND AN INTEGER


    ↝ A LIST WITH TWO ELEMENTS


    ↝ A SYMBOL NAMED INC


    ↝ AND A SYMBOL NAMED X

    View full-size slide

  36. “…HOMOICONICITY IS A PROPERTY OF SOME
    PROGRAMMING LANGUAGES IN WHICH THE CODE USED TO
    EXPRESS A PROGRAM IS WRITTEN USING THE DATA
    STRUCTURES OF THAT LANGUAGE.
    🤯

    View full-size slide

  37. CODE = DATA
    “…HOMOICONICITY IS A PROPERTY OF SOME
    PROGRAMMING LANGUAGES IN WHICH THE CODE
    USED TO EXPRESS A PROGRAM IS WRITTEN USING
    THE DATA STRUCTURES OF THAT LANGUAGE.
    🤯

    View full-size slide

  38. ↝ REACT ELEMENTS ARE JUST DATA


    ↝ JUST LIKE IN LISP, REACT COMPONENTS CAN
    MANIPULATE THEIR CHILDREN AND RETURN
    COMPLETELY DIFFERENT THINGS

    View full-size slide

  39. 🤓💻
    EXPERIMENT #2


    PATTERN MATCHING IN REACT

    View full-size slide

  40. /
    / .
    .
    .


    export function isWhen(


    child: ElementWithMetadataUnion


    ): child is ElementWithMetadata>
    >
    {


    return child.element.type === When;


    }


    /
    / .
    .
    .


    export function nodesToElementWithMetadata(


    children: ReactNode


    ) {


    return Children.toArray(children).map((element, idx)
    =
    >
    ({


    element: element,


    position: idx,


    })) as Array>
    >
    ;


    }


    /
    / .
    .
    .

    View full-size slide

  41. const supportsSensor
    =
    ()
    =
    >
    Boolean(window.AmbientLightSensor);


    const AmbientLight
    =
    React.lazy(()
    =
    >
    import("./AmbientLight"));


    const Fallback
    =
    React.lazy(()
    =
    >
    import("./Fallback"));


    export default function MyComponent() {


    const { Match, When, Otherwise }
    =
    usePatternMatch();


    return (
































    );


    }

    View full-size slide

  42. const supportsSensor
    =
    ()
    =
    >
    Boolean(window.AmbientLightSensor);


    const AmbientLight
    =
    React.lazy(()
    =
    >
    import("./AmbientLight"));


    const Fallback
    =
    React.lazy(()
    =
    >
    import("./Fallback"));


    export default function MyComponent() {


    const { Match, When, Otherwise }
    =
    usePatternMatch();


    return (
































    );


    }
    PATTERN MATCHING


    + REACT.SUSPENSE


    + REACT.LAZY()


    = USERS DOWNLOAD ONLY THE
    ACTUAL COMPONENT BUNDLE
    THAT MATCHES A CONDITION

    View full-size slide

  43. const supportsSensor
    =
    ()
    =
    >
    Boolean(window.AmbientLightSensor);


    const AmbientLight
    =
    React.lazy(()
    =
    >
    import("./AmbientLight"));


    const Fallback
    =
    React.lazy(()
    =
    >
    import("./Fallback"));


    export default function MyComponent() {


    const { Match, When, Otherwise }
    =
    usePatternMatch();


    return (
































    );


    }
    PATTERN MATCHING


    + REACT.SUSPENSE


    + REACT.LAZY()


    = USERS DOWNLOAD ONLY THE
    ACTUAL COMPONENT BUNDLE
    THAT MATCHES A CONDITION
    MANIPULATING BASED ON
    ELEMENTS DATA.

    View full-size slide

  44. HTTPS://GITHUB.COM/


    YTHECOMBINATOR/REACT-MATCHEZ

    View full-size slide

  45. Coroutines
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  46. 1. A GENERATOR (PRODUCER) THAT
    CAN ALSO CONSUME VALUES.

    View full-size slide

  47. 1.
    A GENERATOR (PRODUCER) THAT
    CAN ALSO CONSUME VALUES.
    ↝ JAVASCRIPT GENERATORS CAN
    CONSUME VALUES


    ↝ BY THIS DEFINITION, THEY ARE
    COROUTINES

    View full-size slide

  48. 2. A GENERATOR THAT CAN RESOLVE
    ASYNCHRONOUS VALUES, LIKE
    ASYNC/AWAIT.

    View full-size slide

  49. 2. ↝ THIS IS THE MOST COMMON
    MEANING OF “COROUTINE” IN
    THE JAVASCRIPT WORLD


    ↝ WE HAD CO AND BLUEBIRD,
    WHICH HAD ASYNC/AWAIT
    IMPLEMENTATIONS BASED ON
    GENERATORS
    A GENERATOR THAT CAN RESOLVE
    ASYNCHRONOUS VALUES, LIKE
    ASYNC/AWAIT.

    View full-size slide

  50. 3. A GENERATOR THAT CAN YIELD
    WITH A STACKFUL CONTINUATION

    View full-size slide

  51. 3. ↝ = DEEP AWAIT


    ↝ WITH SUSPENSE, WE CAN
    PAUSE RECONCILIATION AT ANY
    DEPTH
    A GENERATOR THAT CAN YIELD
    WITH A STACKFUL CONTINUATION
    🤯

    View full-size slide

  52. Fibers
    CONTROL IS PASSED TO A
    SCHEDULER WHICH DETERMINES
    WHAT TO RUN NEXT
    ↝ = CONTROLLED AT THE LEVEL OF THE
    OPERATING SYSTEM OR FRAMEWORK


    ↝ E.G. NODE.JS EVENT LOOP

    View full-size slide

  53. Coroutines
    CONTROL IS PASSED TO THE CALLER
    AND HANDLED BY APPLICATION
    CODE
    Fibers
    CONTROL IS PASSED TO A
    SCHEDULER WHICH DETERMINES
    WHAT TO RUN NEXT

    View full-size slide

  54. Coroutines &
    React
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  55. COROUTINES APPEARED WHEN WORK ON FIBER WAS FIRST
    GOING AS A SPECIFIC COMPONENT TYPE.
    THE IDEA BEHIND COROUTINES — AS
    OPPOSED TO FIBERS — WAS TO GIVE
    COMPONENTS EXPLICIT CONTROL OVER
    YIELDING AND RESUMPTION.

    View full-size slide

  56. HTTPS://GITHUB.COM/FACEBOOK/REACT/


    PULL/6859

    View full-size slide

  57. ↝ COROUTINES PER SI IN REACT NO LONGER EXIST.


    ↝ IT WILL BE FASCINATING TO SEE WHAT FORM
    COROUTINES TAKE WHEN THEY RETURN TO REACT FIBER.

    View full-size slide

  58. Coroutines &
    Concurrent
    React
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  59. HTTPS://WWW.YOUTUBE.COM/WATCH?
    V=NLF0N9SACD4

    View full-size slide

  60. function resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    resourcefulOperation(value);


    return {result};


    }

    View full-size slide

  61. 🤓💻
    EXPERIMENT #3


    BUILDING A COROUTINES-BASED SCHEDULER

    View full-size slide

  62. function resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    resourcefulOperation(value);


    return {result};


    }

    View full-size slide

  63. function* resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    while (true) {


    yield;


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    }


    const initialValue
    =
    0;


    const scheduler
    =
    new Scheduler(resourcefulOperation, initialValue);


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    scheduler.performUnitOfWork(value);


    return {result};


    }


    View full-size slide

  64. function* resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    while (true) {


    yield;


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    }


    const initialValue
    =
    0;


    const scheduler
    =
    new Scheduler(resourcefulOperation, initialValue);


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    scheduler.performUnitOfWork(value);


    return {result};


    }


    /
    /
    PROMOTED TO A GENERATOR.
    /
    /
    YIELDING INSIDE AN INFINITE LOOP.
    /
    /
    DOING CONCURRENT STUFF.

    View full-size slide

  65. enum SchedulerState {


    IDLE
    =
    "IDLE",


    PENDING
    =
    "PENDING",


    DONE
    =
    "DONE",


    }


    class Scheduler {


    state: SchedulerState;


    result: T;


    worker: (data: T)
    =
    >
    Generator;


    iterator: Generator;


    constructor(worker: (data: T)
    =
    >
    Generator, initialResult: T) {


    this.state
    =
    SchedulerState.IDLE;


    this.worker
    =
    worker;


    this.result
    =
    initialResult;


    }


    performUnitOfWork(data: T) {


    switch (this.state) {


    case "IDLE":


    this.state
    =
    SchedulerState.PENDING;


    this.iterator
    =
    this.worker(data);


    throw Promise.resolve();


    case "PENDING":


    const { value, done }
    =
    this.iterator.next();


    if (done) {


    this.result
    =
    value;


    this.state
    =
    SchedulerState.DONE;


    return value;


    }


    throw Promise.resolve();


    case "DONE":


    this.state
    =
    SchedulerState.IDLE;


    return this.result;


    }


    }


    }
    🤯

    View full-size slide

  66. enum SchedulerState {


    IDLE
    =
    "IDLE",


    PENDING
    =
    "PENDING",


    DONE
    =
    "DONE",


    }


    class Scheduler {


    state: SchedulerState;


    result: T;


    worker: (data: T)
    =
    >
    Generator;


    iterator: Generator;


    constructor(worker: (data: T)
    =
    >
    Generator, initialResult: T) {


    this.state
    =
    SchedulerState.IDLE;


    this.worker
    =
    worker;


    this.result
    =
    initialResult;


    }


    performUnitOfWork(data: T) {


    switch (this.state) {


    case "IDLE":


    this.state
    =
    SchedulerState.PENDING;


    this.iterator
    =
    this.worker(data);


    throw Promise.resolve();


    case "PENDING":


    const { value, done }
    =
    this.iterator.next();


    if (done) {


    this.result
    =
    value;


    this.state
    =
    SchedulerState.DONE;


    return value;


    }


    throw Promise.resolve();


    case "DONE":


    this.state
    =
    SchedulerState.IDLE;


    return this.result;


    }


    }


    }
    🤯

    View full-size slide

  67. DID WE JUST


    useTransition’ED? 🤔

    View full-size slide

  68. function resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    function ResourcefulComponent(props: { value: number }) {


    const { value }
    =
    props;


    const result
    =
    resourcefulOperation(value);


    return {result};


    }

    View full-size slide

  69. function resourcefulOperation(value: number) {


    let newValue
    =
    String(value);


    for (let i
    =
    0; i < 1000000; i++) {


    newValue
    =
    `${value} + ${i}
    =
    ${value + i}`;


    }


    return newValue;


    }


    function ResourcefulComponent(props: { value: number }) {


    const [_, startTransition]
    =
    useTransition();


    const [result, setResult]
    =
    useState("");


    useEffect(()
    =
    >
    {


    startTransition(()
    =
    >
    {


    const newResult
    =
    resourcefulOperation(props.value);


    setResult(newResult);


    });


    }, [props.value]);


    return {result};


    }

    View full-size slide

  70. YES, WE DID 🤓
    (USING SOME COROUTINES MAGIC)

    View full-size slide

  71. ↝ THERE’S NO USE OF WORKERS OR WASM FOR
    PARALLELISM


    ↝ THERE’S A COOPERATIVE MULTITASKING MODEL


    ↝ A SINGLE RENDERING THREAD, BUT INTERRUPTIBLE
    SO THAT RENDERING CAN BE INTERLEAVED WITH OTHER
    MAIN THREAD TASKS AND OTHER REACT RENDERS

    View full-size slide

  72. ↓ ORIGINAL RENDER TASK
    USER INPUT →
    ↑ HIGHER PRIORITY RENDER TASK
    ↓ RESUME ORIGINAL RENDER TASK

    View full-size slide

  73. ↝ AN UPDATE CAN HAPPEN IN THE BACKGROUND,
    WITHOUT BLOCKING ANOTHER IN RESPONSE TO NEW
    INPUT


    ↝ THE SCHEDULER SWITCHES TO THE MORE URGENT
    RENDERING TASK, THEN PICKS THE ORIGINAL TASK UP
    AFTER THAT HAS FINISHED

    View full-size slide

  74. ↝ IT YIELDS EXECUTION IS BACK TO THE MAIN THREAD
    EVERY 5MS


    ↝ IT'S SMALLER THAN A SINGLE FRAME EVEN ON
    120FPS DEVICES, SO IT WON'T BLOCK ANIMATIONS


    ↝ MOST INDIVIDUAL COMPONENTS DON'T TAKE LONGER
    THAN A SINGLE FRAME TO RENDER


    ↝ IN PRACTICE, RENDERING IS EFFECTIVELY
    INTERRUPTIBLE

    View full-size slide

  75. Coroutines out
    there
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  76. ↝ ASYNCHRONY IN JAVASCRIPT IS CONTAGIOUS


    ↝ IF ANY FUNCTION IS ASYNC, THEN EVERYTHING THAT
    CALLS IT MUST ALSO BE ASYNC…


    ↝ …AND SO ON UNTIL THE ENTIRE PROGRAM
    IS ASYNCHRONOUS 🤷

    View full-size slide

  77. ↝ ASYNCHRONY IN JAVASCRIPT ISN’T FREE


    ↝ EVERY ASYNCHRONOUS FUNCTION CALL HAS TO:


    ↝ ALLOCATE CALLBACKS


    ↝ STORE THEM SOMEWHERE


    ↝ AND TAKE A TRIP BACK TO THE EVENT LOOP BEFORE
    INVOKING THOSE CALLBACKS

    View full-size slide

  78. ↝ ITS API HAS TWO MAIN FUNCTIONS FOR COMPILING
    SASS FILES: ONE SYNC AND ONE ASYNC


    ↝ THE ASYNC ONE BECAME WIDELY USED IN PRACTICE
    BECAUSE IT ENABLED ASYNC PLUGINS (E.G. WEBPACK’S
    SASS-LOADER)

    View full-size slide

  79. ↝ FOR NODE SASS, THE PERFORMANCE DIFFERENCE WAS
    NEGLIGIBLE, BECAUSE IT WAS BUILT ON C++


    ↝ HOWEVER, DART SASS RUNS AS PURE JAVASCRIPT,
    WHICH MAKES IT SUBJECT TO JAVASCRIPT’S ASYNC
    RULES

    View full-size slide

  80. ↝ THE ASYNC VERSION IN DART SASS WAS 2-3X SLOWER
    THAN THE SYNC ONE


    ↝ THEY STARTED USING NODE-FIBERS TO IMPLEMENT THE
    ASYNC API USING THE FAST, SYNC, CODE

    View full-size slide

  81. HTTPS://GITHUB.COM/


    LAVERDET/NODE-FIBERS

    View full-size slide

  82. Effect Handlers
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  83. ↝ EFFECTS ASK THE CALLING ENVIRONMENT TO HANDLE A
    PARTICULAR TASK


    ↝ WHEN AN EFFECT IS USED, THE NEAREST EFFECT
    HANDLER IS CALLED, WHICH ALLOWS YOU TO RUN
    CODE IN RESPONSE TO THE EFFECT AND RETURN
    SOME VALUE.
    🤯

    View full-size slide

  84. HTTPS://OVERREACTED.IO/


    ALGEBRAIC-EFFECTS-FOR-THE-REST-OF-US

    View full-size slide

  85. function getName(user) {


    let name
    =
    user.name;


    if (name === null) {


    name
    =
    perform 'ask_name';


    }


    return name;


    }


    const arya
    =
    { name: null, friendNames: [] };


    const gendry
    =
    { name: 'Gendry', friendNames: [] };


    try {


    getName(arya);


    }


    handle (effect) {


    if (effect === 'ask_name') {


    resume with 'Arya Stark';


    }


    }

    View full-size slide

  86. function getName(user) {


    let name
    =
    user.name;


    if (name === null) {


    name
    =
    perform 'ask_name';


    }


    return name;


    }


    const arya
    =
    { name: null, friendNames: [] };


    const gendry
    =
    { name: 'Gendry', friendNames: [] };


    try {


    getName(arya);


    }


    handle (effect) {


    if (effect === 'ask_name') {


    resume with 'Arya Stark';


    }


    }

    View full-size slide

  87. function getName(user) {


    let name
    =
    user.name;


    if (name === null) {


    name
    =
    perform 'ask_name';


    }


    return name;


    }


    const arya
    =
    { name: null, friendNames: [] };


    const gendry
    =
    { name: 'Gendry', friendNames: [] };


    try {


    getName(arya);


    }


    handle (effect) {


    if (effect === 'ask_name') {


    resume with 'Arya Stark';


    }


    }
    /
    /
    THROW → PERFORM
    /
    /
    CATCH → HANDLE
    /
    /
    LETS US JUMP BACK TO WHERE WE
    PERFORMED THE EFFECT

    View full-size slide

  88. Effect
    handlers in
    React
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  89. 1. LAYOUT ALGORITHM

    View full-size slide

  90. THE REACT TEAM APPARENTLY SPENT
    SOME TIME EXPERIMENTING WITH
    EFFECT-HANDLER CONTROL STRUCTURES
    FOR MANAGING LAYOUT

    View full-size slide

  91. HTTPS://GITHUB.COM/REACTJS/REACT-FUTURE/BLOB/MASTER/
    04%20-%20LAYOUT/PROTOTYPE/INDEX.JS

    View full-size slide

  92. 2. CONTEXT API DRAFTS

    View full-size slide

  93. THEY’VE ALSO REMODELED THE CONTEXT API
    USING ALGEBRAIC EFFECTS

    View full-size slide

  94. HTTPS://GITHUB.COM/REACTJS/RFCS/


    BLOB/MAIN/TEXT/0002-NEW-VERSION-OF-CONTEXT.MD

    View full-size slide

  95. 3. SIDE EFFECTS WITHIN A
    COMPONENT

    View full-size slide

  96. HTTPS://GITHUB.COM/


    REACTJS/REACT-BASIC#ALGEBRAIC-EFFECTS

    View full-size slide

  97. function ThemeBorderColorRequest() { }


    function FancyBox(children) {


    const color
    =
    raise new ThemeBorderColorRequest();


    return {


    borderWidth: '1px',


    borderColor: color,


    children: children


    };


    }


    function BlueTheme(children) {


    return try {


    children();


    } catch effect ThemeBorderColorRequest
    -
    >
    [, continuation] {


    continuation('blue');


    }


    }


    function App(data) {


    return BlueTheme(


    FancyUserList.bind(null, data.users)


    );


    }

    View full-size slide

  98. function ThemeBorderColorRequest() { }


    function FancyBox(children) {


    const color
    =
    raise new ThemeBorderColorRequest();


    return {


    borderWidth: '1px',


    borderColor: color,


    children: children


    };


    }


    function BlueTheme(children) {


    return try {


    children();


    } catch effect ThemeBorderColorRequest
    -
    >
    [, continuation] {


    continuation('blue');


    }


    }


    function App(data) {


    return BlueTheme(


    FancyUserList.bind(null, data.users)


    );


    }
    /
    /
    THROW → RAISE
    /
    /
    CATCH → CATCH EFFECT

    View full-size slide

  99. 4. SUSPENSE INTERNALS

    View full-size slide

  100. 🙋✋
    QUESTION #2


    HAVE YOU EVER BUILT ANY SUSPENSE-READY API?

    View full-size slide

  101. HTTPS://GITHUB.COM/FACEBOOK/REACT/BLOB/MAIN/
    PACKAGES/REACT-CACHE/SRC/REACTCACHEOLD.JS

    View full-size slide

  102. A COMPONENT IS ABLE TO SUSPEND THE
    FIBER IT IS RUNNING IN BY THROWING A
    PROMISE, WHICH IS CAUGHT AND
    HANDLED BY THE FRAMEWORK.

    View full-size slide

  103. THROW → HANDLE → RESUME PATTERN.
    A COMPONENT IS ABLE TO SUSPEND THE
    FIBER IT IS RUNNING IN BY THROWING A
    PROMISE, WHICH IS CAUGHT AND
    HANDLED BY THE FRAMEWORK.

    View full-size slide

  104. Conclusions
    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR

    View full-size slide

  105. 1. REACT FIBER WAS A REWRITE OF
    REACT FOCUSED ON GIVING MORE
    LOW-LEVEL CONTROL OVER
    PROGRAM EXECUTION

    View full-size slide

  106. 1.
    ↝ FIBERS AS A LOW-LEVEL
    COOPERATIVE WAY TO MODEL
    EXECUTION


    ↝ ALGEBRAIC EFFECTS AS A WAY
    TO HANDLE EFFECTS WHERE
    THESE AND THEIR BEHAVIOR
    ARE INDEPENDENT
    LOW-LEVEL CONTROL OVER
    PROGRAM EXECUTION

    View full-size slide

  107. 2. REACT TRIES TO ADDRESS THE
    LACK OF SOME JAVASCRIPT
    FEATURES/LANGUAGE-LEVEL
    RESOURCES BY IMPLEMENTING
    SOME ALTERNATIVE SOLUTIONS TO
    ACHIEVE SIMILAR BEHAVIORS

    View full-size slide

  108. 3. UNDERSTANDING THESE
    INTERNALS AND THEIR
    RATIONALES HELPS US IMPLEMENT
    OUR OWN ABSTRACTIONS

    View full-size slide

  109. HTTPS://WWW.YOUTUBE.COM/WATCH?
    V=ADNJ3FYDEAO

    View full-size slide

  110. 4. REACT IS NOT REACTIVE, BUT IT
    FEELS CONCURRENT

    View full-size slide

  111. 5. THE FACT WE'RE DISCUSSING ALL
    OF THESE TOPICS SHOWS THAT
    REACT ACTS AS A DEMOCRATIC
    AGENT FOR THIS KIND OF
    KNOWLEDGE IN THE FRONT-END
    WORLD

    View full-size slide

  112. THIS IS THE EIGHT-YEARS-AGO-ME GIVING A TALK ABOUT
    IONIC AT AN IOS DEVELOPERS MEETUP TELLING THEM
    THAT ANGULAR WOULD BE THE FUTURE.

    View full-size slide

  113. 6. DON’T ALWAYS TRUST ALL OF MY
    SPECULATIONS/FUTURE
    PREDICTIONS 🤷

    View full-size slide

  114. HTTPS://SPEAKERDECK.COM/


    YTHECOMBINATOR/REACT-NEXT-2022

    View full-size slide

  115. Israel


    Spain


    India


    Czech Republic


    Mexico
    We’re hiring!


    Mostly in:

    View full-size slide

  116. Israel


    Spain


    India


    Czech Republic


    Mexico
    We’re hiring!


    View full-size slide

  117. MATHEUS ALBUQUERQUE
    THAT’S ALL, FOLKS! THANKS!
    QUESTIONS?

    View full-size slide