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

๐Ÿ‡ณ๐Ÿ‡ฑ Frontmania 2022 - Inside Fiber

๐Ÿ‡ณ๐Ÿ‡ฑ Frontmania 2022 - Insideย Fiber

โ„น๏ธ 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

October 04, 2022
Tweet

More Decks by Matheus Albuquerque

Other Decks in Technology

Transcript

  1. Iโ€™M MATHEUS ๐Ÿ™‹ โ† @YTHECOMBINATOR ON THE WEB โ† SR.

    SOFTWARE ENGINEER @MEDALLIA โ† MENTOR @TECHLABS
  2. #1 REACT SOURCE CODE IS CONSTANTLY CHANGING, AND SOME THOUGHTS

    ARE SPECULATIONS INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
  3. #2 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR ๐Ÿคฏ = DEEP DIVE ๐Ÿคฟ, FURTHER DISCUSSIONS AFTER THE SESSION
  4. function add(x,y) { const result = x + y; return

    result; } add(2, 2) STACK FRAMES
  5. let frame: Frame = { return: frame, fn: add, parameters:

    [2, 2], localVariables: { result: 4, }, } STACK FRAMES
  6. 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, }, } STACK FRAMES
  7. โ† 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 FIBERS
  8. 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. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  9. 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. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  10. 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. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  11. 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. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  12. 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. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE. A UNIT OF WORK.
  13. 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. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE. A UNIT OF WORK. AND THAT MAKES IT A CONVENIENT WAY TO TRACK, SCHEDULE, PAUSE AND ABORT THE WORK.
  14. 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; }
  15. 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; } ๐Ÿคฏ
  16. (let [x 1] (inc x)) ; = > 2 HOMOICONICITY

    PERFORMS A TEMPORARY BINDING (BINDS X TO THE VALUE 1)
  17. INCREMENTS X TO GIVE THE RETURN VALUE OF 2 (let

    [x 1] (inc x)) ; = > 2 HOMOICONICITY
  18. IT CAN BE THOUGHT OF AS A LIST WITH THREE

    ELEMENTS โ† A SYMBOL NAMED LET โ† A VECTOR WITH TWO ELEMENTS โ† A LIST WITH TWO ELEMENTS HOMOICONICITY
  19. IT CAN BE THOUGHT OF AS A LIST WITH THREE

    ELEMENTS โ† A SYMBOL NAMED LET โ† A VECTOR WITH TWO ELEMENTS โ† A LIST WITH TWO ELEMENTS HOMOICONICITY A SYMBOL (X) AND AN INTEGER A SYMBOL (INC) AND A SYMBOL (X)
  20. #QUOTE ๐Ÿค” โ€œโ€ฆ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.โ€ โ€”โ€‰Wikipedia
  21. โ† REACT ELEMENTS ARE JUST DATA โ† JUST LIKE IN

    LISP, REACT COMPONENTS CAN MANIPULATE THEIR CHILDREN AND RETURN COMPLETELY DIFFERENT THINGS HOMOICONICITY
  22. #QUOTE ๐Ÿค” โ€œ[โ€ฆ] Pattern matching consists of specifying patterns to

    which some data should conform and then checking to see if it does and deconstructing the data according to those patterns.โ€ โ€”โ€‰Learn You a Haskell
  23. factorial : : (Integral a) = > a - >

    a factorial 0 = 1 factorial n = n * factorial (n - 1) PATTERN MATCHING
  24. fib : : (Integral a) = > a - >

    a fib 0 = 1 fib 1 = 1 fib n | n > = 2 = fib (n-1) + fib (n-2) PATTERN MATCHING factorial =
  25. / / . . . export function isWhen<Shape extends {}>(

    child: ElementWithMetadataUnion<Shape> ): child is ElementWithMetadata<WhenProps<Shape > > { return child.element.type === When; } / / . . . export function nodesToElementWithMetadata<Shape extends {}>( children: ReactNode ) { return Children.toArray(children).map((element, idx) = > ({ element: element, position: idx, })) as Array<ElementWithMetadata<Shape > > ; } / / . . .
  26. / / . . . export function isWhen<Shape extends {}>(

    child: ElementWithMetadataUnion<Shape> ): child is ElementWithMetadata<WhenProps<Shape > > { return child.element.type === When; } / / . . . export function nodesToElementWithMetadata<Shape extends {}>( children: ReactNode ) { return Children.toArray(children).map((element, idx) = > ({ element: element, position: idx, })) as Array<ElementWithMetadata<Shape > > ; } / / . . .
  27. 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 ( <Suspense fallback="Loading"> <Match> <When predicate={supportsSensor}> <AmbientLight /> </When> <Otherwise> <Fallback /> </Otherwise> </Match> </Suspense> ); } PATTERN MATCHING
  28. 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 ( <Suspense fallback="Loading"> <Match> <When predicate={supportsSensor}> <AmbientLight /> </When> <Otherwise> <Fallback /> </Otherwise> </Match> </Suspense> ); } PATTERN MATCHING + REACT.SUSPENSE + REACT.LAZY() = USERS DOWNLOAD ONLY THE COMPONENT BUNDLE THAT MATCHES
  29. const supportsSensor + REACT.SUSPENSE + REACT.LAZY() = USERS DOWNLOAD ONLY

    THE COMPONENT BUNDLE THAT MATCHES MANIPULATING BASED ON ELEMENTS DATA.
  30. USING FIBERS, REACT CAN: โ† PAUSE, RESUME, AND RESTART RENDERING

    WORK ON COMPONENTS AS NEW UPDATES COME IN โ† REUSE PREVIOUSLY COMPLETED WORK โ† SPLIT WORK INTO CHUNKS AND PRIORITIZE TASKS BASED ON IMPORTANCE FIBERS IN REACT (RECAP)
  31. โ† A FIBER IS A GENERIC MODEL OF EXECUTION WHERE

    EACH UNIT WORKS TOGETHER COOPERATIVELY โ† FIBERS ARE A COMMON RESOURCE IN SOME OPERATING SYSTEMS (E.G. WINDOWS) AND IN SOME PROGRAMMING LANGUAGES (E.G. OCAML) FIBERS OUT THERE
  32. #1 A GENERATOR (PRODUCER) THAT CAN ALSO CONSUME VALUES. INSIDE

    FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
  33. #1 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR โ† JAVASCRIPT GENERATORS CAN CONSUME VALUES โ† BY THIS DEFINITION, THEY ARE COROUTINES A GENERATOR (PRODUCER) THAT CAN ALSO CONSUME VALUES.
  34. #2 A GENERATOR THAT CAN RESOLVE ASYNCHRONOUS VALUES, LIKE ASYNC/AWAIT.

    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
  35. #2 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR โ† 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 VALUES, LIKE ASYNC/AWAIT.
  36. #3 A GENERATOR THAT CAN YIELD WITH A STACKFUL CONTINUATION

    INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
  37. #3 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR โ† "DEEP AWAIT" โ† e.g. WITH SUSPENSE, WE CAN PAUSE RECONCILIATION AT ANY DEPTH A GENERATOR THAT CAN YIELD WITH A STACKFUL CONTINUATION
  38. 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
  39. 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
  40. 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.
  41. COROUTINES & REACT โ† COROUTINES PER SI IN REACT NO

    LONGER EXIST. โ† IT WILL BE FASCINATING TO SEE WHAT FORM COROUTINES TAKE WHEN THEY RETURN TO REACT FIBER.
  42. 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 <p>{result}</p>; }
  43. 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 <p>{result}</p>; }
  44. 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 <p>{result}</p>; }
  45. 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 <p>{result}</p>; } PROMOTED TO A GENERATOR YIELDING EXECUTION DOING CONCURRENT TASKS
  46. enum SchedulerState { IDLE = "IDLE", PENDING = "PENDING", DONE

    = "DONE", } class Scheduler<T> { 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; } } }
  47. 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; } }
  48. 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 <p>{result}</p>; }
  49. 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 <p>{result}</p>; }
  50. โ† A COOPERATIVE MULTITASKING MODEL โ† A SINGLE INTERRUPTIBLE RENDERING

    THREAD โ† RENDERING CAN BE INTERLEAVED WITH OTHER MAIN THREAD TASKS AND OTHER REACT RENDERS โ† AN UPDATE CAN HAPPEN IN THE BACKGROUND WITHOUT BLOCKING THE RESPONSE TO NEW INPUT COROUTINES & SCHEDULING
  51. โ†“ ORIGINAL RENDER TASK USER INPUT โ†’ โ†‘ HIGHER PRIORITY

    RENDER TASK โ†“ RESUME ORIGINAL RENDER TASK
  52. โ† IT YIELDS EXECUTION IS BACK TO THE MAIN THREAD

    EVERY 5MS โ† IT'S SMALLER THAN A SINGLE FRAME EVEN ON 120FPS, SO IT WON'T BLOCK ANIMATIONS โ† IN PRACTICE, RENDERING IS INTERRUPTIBLE COROUTINES & SCHEDULING
  53. COROUTINES & SCHEDULING const DailyVisitors = () = > {

    const [data, setData] = useState(initialData); useEffect(() = > { setData(initialData); }, []); const onChange = (newData) = > { setData(newData); }; return ( <Dashboard data={data} initialData={initialData} onChange={onChange} /> ); }; export default DailyVisitors;
  54. COROUTINES & SCHEDULING const DailyVisitors = () = > {

    const [data, setData] = useState(initialData); const [, startTransition] = useTransition(); useEffect(() = > { setData(initialData); }, []); const onChange = (newData) = > { startTransition(() = > { setData(newData); }); }; return ( <Dashboard data={data} initialData={initialData} onChange={onChange} /> ); }; export default DailyVisitors;
  55. โ† 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 ๐Ÿคท ASYNCHRONY & JS
  56. โ† ASYNCHRONY IN JAVASCRIPT ISNโ€™T FREE โ† EVERY ASYNCHRONOUS FUNCTION

    CALL HAS TO: โ† ALLOCATE CALLBACKS & STORE THEM SOMEWHERE โ† TAKE A TRIP BACK TO THE EVENT LOOP BEFORE INVOKING THOSE CALLBACKS ASYNCHRONY & JS
  57. โ† 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) ASYNCHRONY & SASS
  58. โ† 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 ASYNCHRONY & SASS
  59. โ† 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 ASYNCHRONY & SASS
  60. ๐Ÿคฏ APPROACH TO REASONING ABOUT COMPUTATIONAL EFFECTS IN PURE CONTEXTS

    โ† EFFECT โ‡ข A SET OF OPERATIONS โ† EFFECT HANDLER โ‡ข RESPONSIBLE FOR HANDLING THE SEMANTICS OF HOW TO IMPLEMENT EFFECTS EFFECT HANDLERS
  61. (* state.eff *) type user = string * int effect

    Get: user effect Set: user - > unit ๐Ÿคฏ EFFECT HANDLERS IN EFF
  62. (* state.eff *) type user = string * int effect

    Get: user effect Set: user - > unit A USER WITH A NAME AND AGE EFFECT HANDLERS IN EFF
  63. (* state.eff *) type user = string * int effect

    Get: user effect Set: user - > unit WE DEFINE EFFECTS WITH THE effect KEYWORD AND A TYPE SIGNATURE. EFFECT HANDLERS IN EFF
  64. let state = handler | y - > fun currentState

    - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; ๐Ÿคฏ EFFECT HANDLERS IN EFF
  65. let state = handler | y - > fun currentState

    - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; WE HAVE A handler WITH THREE BRANCHES, AND ALL OF THEM RETURN A FUNCTION. EFFECT HANDLERS IN EFF
  66. let state = handler | y - > fun currentState

    - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; NO EFFECT (WHEN WE REACH THE END OF THE BLOCK). y IS THE RETURN VALUE. EFFECT HANDLERS IN EFF
  67. let state = handler | y - > fun currentState

    - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; MATCHING OUR EFFECTS. EFFECT HANDLERS IN EFF
  68. let state = handler | y - > fun currentState

    - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; k IS A CONTINUATION. IT REPRESENTS THE REST OF THE COMPUTATION AFTER WHERE WE PERFORM AN EFFECT. EFFECT HANDLERS IN EFF
  69. 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'; } }
  70. 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'; } }
  71. 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
  72. โ† IT DOESN'T REALLY MATTER HOW WE HOLD STATE. IF

    WE WERE TO CHANGE IN THE FUTURE, WEโ€™D NEED TO START HANDLING PROMISES, WHICH WOULD REQUIRE CHANGES ACROSS EVERYTHING. โ† WITH ALGEBRAIC EFFECTS, WE CAN SIMPLY STOP THE CURRENT PROCESS ALTOGETHER UNTIL OUR EFFECTS ARE FINISHED. EFFECT HANDLERS
  73. THE REACT TEAM APPARENTLY SPENT SOME TIME EXPERIMENTING WITH EFFECT-

    HANDLER CONTROL STRUCTURES FOR MANAGING LAYOUT
  74. #3 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR SIDE EFFECTS WITHIN A COMPONENT
  75. 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) ); }
  76. 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
  77. HOOKS API โ† ALGEBRAIC EFFECTS = A SET OF OPERATIONS

    AND A SET OF EFFECT HANDLERS โ† THE OPERATIONS HERE ARE OUR HOOKS (E.G. useState, useEffect, AND SO ON) โ† WE HAVE TO SET UP HANDLERS IN EFF; IN REACT THEY'RE SET UP AS PART OF THE RENDER CYCLE
  78. HOOKS API โ† REACT IS RESPONSIBLE FOR MUCH OF THE

    IMPLEMENTATION OF WHEN/HOW OUR EFFECTS RUN โ† IT ALLOWS US TO STASH ENORMOUS AMOUNTS OF COMPLEXITY WITHIN REACT โ† BY SPLITTING EFFECTS AND RENDERING, WE ALLOW IT TO RELIEVE US OF SOME COMPLEXITY
  79. A COMPONENT IS ABLE TO SUSPEND THE FIBER IT IS

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

    RUNNING IN BY THROWING A PROMISE, WHICH IS CAUGHT AND HANDLED BY THE FRAMEWORK. THROW โ†’ HANDLE โ†’ RESUME PATTERN.
  81. #QUOTE ๐Ÿค” โ€œAt my heart, I am something like the

    goto instruction; my creation sets the label, and my methods do the jump. However, this is a really powerful kind of goto instruction. [โ€ฆ]โ€ โ€”โ€‰GNU Smalltalk Continuation documentation
  82. โ† ITโ€™S AN ABSTRACTION THAT REPRESENTS THE REMAINING STEPS IN

    A COMPUTATION, AFTER WHERE WE PERFORM AN EFFECT. โ† IT'S A CONTROL FLOW PRIMITIVE. โ† DIFFERENT FROM goto. ALL THE VARIABLES, POINTERS, ETC. ARE VALID. CONTINUATIONS
  83. function performWork(deadline) { while (tasks.length > 0) { const task

    = tasks.shift(); doTask(task); if ( tasks.length > 0 & & !deadline.didTimeout & & deadline.timeRemaining() < = 0 ) { return performWork; } } } scheduleWork(performWork); CONTINUATIONS IN REACT
  84. โ† IT HANDLES A QUEUE OF TASKS IN A WHILE

    LOOP โ† IF THERE ARE STILL TASKS ON THE QUEUE, IT RETURNS performWork AND SCHEDULE IT FOR RESUMPTION AT SOME LATER TIME โ† IN THIS CONTEXT, IT REPRESENTS THE CONTINUATION OF A QUEUE OF TASKS CONTINUATIONS IN REACT
  85. async function doWork() { while (true) { let hasMoreWork =

    doSomeWork(); if (!hasMoreWork) { return; } if (!navigator.scheduling.isInputPending()) { continue; } await scheduler.yield(); } } ๐Ÿคฏ CONTINUATIONS ON THE WEB
  86. #1 REACT FIBER WAS A REWRITE OF REACT FOCUSED ON

    GIVING MORE LOW-LEVEL CONTROL OVER PROGRAM EXECUTION INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
  87. #1 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR โ† 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 EXECUTION
  88. #2 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR REACT TRIES TO ADDRESS THE LACK OF SOME JAVASCRIPT FEATURES/ LANGUAGE-LEVEL RESOURCES BY IMPLEMENTING SOME ALTERNATIVE SOLUTIONS TO ACHIEVE SIMILAR BEHAVIORS E.G. EFFECT HANDLERS & CONTINUATIONS
  89. #3 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR UNDERSTANDING SOME OF THESE CONCEPTS GIVES US A BETTER MENTAL MODEL FOR WHAT SOME REACT FEATURES ARE DOING BEHIND THE SCENES E.G. HOOKS AND EFFECT HANDLERS
  90. #4 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR UNDERSTANDING THESE INTERNALS AND THEIR RATIONALES HELPS US IMPLEMENT OUR OWN ABSTRACTIONS E.G. THE COROUTINES-BASED SCHEDULER & THE PATTERN MATCHING COMPONENTS
  91. #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 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR FOR
  92. 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.
  93. #6 INSIDE FIBER: THE IN-DEPTH OVERVIEW YOU WANTED A TLDR

    FOR DONโ€™T ALWAYS TRUST ALL OF MY SPECULATIONS/FUTURE PREDICTIONS ๐Ÿคท