sailei1 / blog

1 stars 0 forks source link

模拟 hook useState useEffect #111

Closed sailei1 closed 3 years ago

sailei1 commented 3 years ago
<script>
  const effectStack = [];
  function subscribe(effect, subs) {
    subs.add(effect);
    effect.deps.add(subs);
  }

  function useState(value) {
    const subs = new Set();

    const getter = () => {
      const effect = effectStack[effectStack.length - 1];
      if (effect) {
        subscribe(effect, subs);
      }
      return value;
    }
    const setter = (nextValue) => {
      value = nextValue;

      for (const sub of [...subs]) {
        sub.execute();
      }
    }
    return [getter, setter];
  }

  function cleanup(effect) {
    for (const dep of effect.deps) {
      dep.delete(effect);
    }
    effect.deps.clear();
  }

  function useEffect(callback) {
    const execute = () => {
      cleanup(effect);
      effectStack.push(effect);

      try {
        callback();
      } finally {
        effectStack.pop();
      }
    }
    const effect = {
      execute,
      deps: new Set()
    }
    execute();
  }
  function useMemo(callback) {
    const [s, set] = useState();
    useEffect(() => set(callback()));
    return s;
  }

  function App() {
    const [name1, setName1] = useState('KaSong');
    const [name2, setName2] = useState('XiaoMing');
    const [showAll, triggerShowAll] = useState(true);

    const whoIsHere = useMemo(() => {
      if (!showAll()) {
        return name1();
      }
      return `${name1()} 和 ${name2()}`;
    })

    useEffect(() => console.log('谁在那儿!', whoIsHere()))

    setName1('KaKaSong');
    triggerShowAll(false);
    setName2('XiaoHong');
    triggerShowAll(true);
  }

  App();

  </script>

摘自 https://juejin.cn/post/6982539854223507492?from=main_page https://codesandbox.io/s/wispy-brook-rrr7x?file=/index.html