react hooks 实现原理猜想

260 阅读2分钟

很久没学习过react了,当时刚了解了hooks时,就感觉这种用法很神奇,也猜想了一下背后的实现原理,今天正好要正式学习一下,所以把自己的猜想先用伪代码写一下,后续可以看看源码到底是怎么实现的。

hooks使用官方给了两个限制规则:

  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
  • 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。

从这个规则里大概也能窥测到一点原理。

我们拿useState来说, useState可以使用多次,但要按顺序(不能条件判断),useState每次返回不同,但是按第一次使用的顺序返回,这应该是个状态机(没了解过,猜的)。直接上码分析:

const states = Object.create(null); // 存放state的地方
const componentId = 1; // 每个组件有个id
let stateId = 0; // 每个组件可以有多个state(多次调用useState)

function useState(defaultValue) {
  stateId += 1;

  if (states[componentId] && states[componentId][stateId]) {
    return states[componentId][stateId];
  }

  if (!states[componentId]) {
    states[componentId] = Object.create(null);
  }

  const state = [defaultValue];
  function setter(value) {
    state[0] = value; // 简单替换
  }
  state[1] = setter;
  states[componentId][stateId] = state;

  return state;
}

function Example() {
  const [count, setCount] = useState(0);
  console.log("count =", count);
  setCount(count + 1);

  const [age, setAge] = useState(42);
  console.log("age = ", age);
  setAge(age + 1);

  console.log("   ");
  console.log("----------");
  console.log("   ");

  return "hello world";
}

// react知道当前渲染的组件id, 所以能从states里找到对应的state
function render() {
  Example();
  stateId = 0;
}

// 组件卸载,销毁state
function destroy() {
  delete states[componentId];
  console.log("destroyed");
  console.log("   ");
  console.log("----------");
  console.log("   ");
}

render();
render();
render();

destroy();

render();
render();
render();

输出结果:

是符合预期的,我们取到了对应的值,还可以更新

可能现在的猜想完全不对,毕竟才看到了使用,文档都没读完呢,后续再学习一下,完善