hooks 灵感

609 阅读1分钟
hooks灵感起源 hook.js
let info = null, schedule = new Set;

const runSchedule = () => {
    const previous = schedule;
    schedule = new Set;
    previous.forEach(({h, c, a, e}) => {
      // avoid running schedules when the hook is
      // re-executed before such schedule happens
      if (e)
        h.apply(c, a);
    });
};

export const getInfo = () => info;

export const isFunction = f => typeof f === 'function';

export const hooked = callback => {
    const current = {h: hook, c: null, a: null, e: 0, i: 0, s: []};
    return hook;
    function hook() {
      const prev = info;
      info = current;
      current.e = current.i = 0;
      try {
        return callback.apply(current.c = this, current.a = arguments);
      }
      finally {
        info = prev;
      }
    }
};

export const reschedule = info => {
    if (!schedule.has(info)) {
      info.e = 1;
      schedule.add(info);
      wait.then(runSchedule);
    }
};

export const wait = new Promise($ => $());

hooks灵感开天辟地reducer.js
import { getInfo, isFunction, reschedule } from './hooks.js';

const getValue = (value, f) => isFunction(f) ? f(value) : f;

export const useReducer = (reducer, value, init) => {
  const info = getInfo();
  const {i, s} = info;
  if (i === s.length)
    s.push({
      $: isFunction(init) ?
          init(value) : getValue(void 0, value), 
      set: value => {
        s[i].$ = reducer(s[i].$, value);
        reschedule(info);
      }
    });
  const {$, set} = s[info.i++];
  return [$, set];
};

export const useState = value => useReducer(getValue, value);

export const useRef = current => {
  const info = getInfo();
  const {i, s} = info;
  if (i === s.length)
    s.push({current});
  return s[info.i++];
};


hooks灵感盘古开创counter.js
import { hooked } from './hooks.js';
import { useState, useRef } from './reducer.js';

const Counter = (start) => {
    const [count, setCount] = useState(start);
    const {current} = useRef({});
    current.increment = () => {
      setCount(count + 1);
    };
    console.log(count);
    return current;
};
  
// logs 1, 1
const comp1 = hooked(Counter)(1);
const comp2 = hooked(Counter)(1);
// logs 2
comp1.increment();