useMemo in React naive implementation

by de Montalembert Jonathan

JavaScript

const React = (function() {

  let currentHook = 0,
    hooks = []

  function memo(fn, deps) {
    const localHook = currentHook
    hooks[localHook] = hooks[localHook] || []
    currentHook++

    if (!hooks[localHook].length) {
      return compute()
    } else {
      const found = hooks[localHook].find((memoized) => {
        return memoized.slice(0, deps.length).every((m, i) => m === deps[i])
      })
      if (found) {
        console.log('from cache', found.slice(-1)[0])
        return found.slice(-1)[0]
      } else {
        return compute()
      }
    }

    function compute() {
      console.log('compute')
      const newOutput = fn.apply(null, deps)
      hooks[localHook] = [...hooks[localHook],
        [...deps, newOutput]
      ]
      return newOutput
    }
  }

  return {
    useMemo: memo,
    useCallback: (fn, deps) => memo(() => fn, deps),
    render: (Component) => {
      const inst = Component()
      currentHook = 0
      inst.render();
      console.log("hooks", hooks)
    }
  }
})()

function sum(a, b) {
  return a + b
}

function View(b) {
  let a = 1, c = 9
  const memoized = React.useMemo(sum, [a, b])
  const memoized2 = React.useMemo(sum, [c, b])
  const callback = React.useCallback(() => sum(a, b), [a, b])
  return {
    render: () => {
      console.log('render', memoized, memoized2, callback())
    }
  }
}

React.render(View.bind(null, 2))
React.render(View.bind(null, 3))
React.render(View.bind(null, 2))