a small incremental UI library for the web
javascript web ui
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add useEffect

garrison cfdb0530 bffa9cb5

+68 -1
+6 -1
demos/todo/todo.tsx
··· 1 1 import * as Noir from '../../js/noir.ts'; 2 - import { useState } from '../../js/hooks.ts'; 2 + import { useState, useEffect } from '../../js/hooks.ts'; 3 3 4 4 function App(props) { 5 5 return ( ··· 11 11 12 12 function List(props) { 13 13 const [count, setCount] = useState(3); 14 + 15 + useEffect(() => { 16 + console.log('in'); 17 + return () => console.log('out'); 18 + }, [count]); 14 19 15 20 const items = []; 16 21 for (i = 0; i < count; i++) {
+27
js/effects.ts
··· 1 + let HEAD = null; 2 + let TAIL = null; 3 + 4 + export function commitSideEffects() { 5 + let node = HEAD; 6 + while(node) { 7 + node.effectFun(); 8 + node = node.next; 9 + } 10 + } 11 + 12 + export function resetSideEffectQueue() { 13 + HEAD = TAIL = null; 14 + } 15 + 16 + export function pushSideEffect(effectFun) { 17 + const node = {effectFun: effectFun, next: null}; 18 + 19 + if (HEAD) { 20 + TAIL.next = node; 21 + TAIL = node; 22 + } 23 + else { 24 + HEAD = node; 25 + TAIL = node; 26 + } 27 + }
+32
js/hooks.ts
··· 1 1 import { queueFiberTree } from './render.ts'; 2 2 import { getCurrentFiber } from './current.ts'; 3 + import { pushSideEffect } from './effects.ts'; 3 4 4 5 export const Hook = { 5 6 State: 'state', 7 + Effect: 'effect', 6 8 }; 7 9 8 10 const { 9 11 State, 12 + Effect, 10 13 } = Hook; 11 14 12 15 function useFiber() { ··· 54 57 55 58 return [value, setValue]; 56 59 } 60 + 61 + export function useEffect(callback, dependencies) { 62 + const fiber = useFiber(); 63 + const pointer = pushHook(fiber, Effect); 64 + 65 + const oldDeps = fiber.hooks[pointer + 2]; 66 + if (!areDependenciesEqual(oldDeps, dependencies)) { 67 + fiber.hooks[pointer + 2] = dependencies; 68 + const oldCleanup = fiber.hooks[pointer + 1]; 69 + 70 + pushSideEffect(() => { 71 + if (oldCleanup !== undefined) oldCleanup(); 72 + const newCleanup = callback(); 73 + fiber.hooks[pointer + 1] = newCleanup; 74 + }); 75 + } 76 + } 77 + 78 + function areDependenciesEqual(oldDeps, newDeps) { 79 + if (oldDeps === undefined) return false; 80 + if (newDeps === oldDeps) return true; 81 + 82 + const length = oldDeps.length; 83 + if (length !== newDeps.length) return false; 84 + for (let i = 0; i < length; i++) { 85 + if (newDeps[i] !== oldDeps[i]) return false; 86 + } 87 + return true; 88 + }
+3
js/render.ts
··· 1 1 import { FiberTag, cloneFiber, reconcileChildren } from './fiber.ts'; 2 2 import { commitTree } from './commit.ts'; 3 3 import { setCurrentFiber } from './current.ts'; 4 + import { commitSideEffects, resetSideEffectQueue } from './effects.ts'; 4 5 import { assert } from './utils.ts'; 5 6 6 7 const { ··· 47 48 48 49 performWork(); 49 50 commitTree(wipFiber); 51 + commitSideEffects(); 52 + resetSideEffectQueue(); 50 53 51 54 WIP_FIBER = null; 52 55 NEXT_WORK_FIBER = null;