在 深入了解react hooks原理Ⅰ 实现了useState
,遗留了两个问题
- 使用多个 useState 是否能够符合预期
- useEffect 是怎么实现的
使用 useState 是否能够符合预期
我们新增一个状态
function Component() { const [count, setCount] = React.useState(1); const [text, setText] = React.useState("hello"); return { render: () => console.log({ count, text }), click: () => setCount(count + 1), say: (text) => setText(text) };}
可以看到,每次render的结果跟我们预期的不一致,每次 count
和 text
都是最后赋值的结果,这时候可以通过数组来存储 useState
,我们改写下React模块,新增一个 hooks
数组来存储state的值
const React = (function () { let hooks = []; // 定义一个hooks数组存储值 let idx = 0; function useState(initVal) { const state = hooks[idx] || initVal; const _idx = idx; // 保留首次useState下标,通过下标可以记录当前state的位置 const setState = (newVal) => { hooks[_idx] = newVal; }; idx++; return [state, setState]; } function render(Component) { const C = new Component(); C.render(); idx = 0; // 每次render完成后,下标置0 return C; } return { useState, render };})();function Component() { const [count, setCount] = React.useState(1); const [text, setText] = React.useState("hello"); return { render: () => console.log({ count, text }), click: () => setCount(count + 1), say: (text) => setText(text) };}
这样结果就一致了
useEffect实现
我们先来看看 useEffect
的语法
useEffect(callback, deps);
第一个参数是回调 callback
,第二个参数是依赖的数组 deps
回到上面的 useState
实现,我们通过新增 hooks
数组存储 useState
的值,也可以继续通过 hooks
数组来存储依赖的值,也是我们可以实现一个 useEffect
function useEffect(cb, deps) { // 旧的依赖值,这里的依赖是存放在hooks的所有state后面 const oldDeps = hooks[idx]; let hasChanged = true; if (oldDeps) { // 通过 Object.is 来判断依赖是否改变 hasChanged = deps.some((val, i) => !Object.is(val, oldDeps[i])); } if (hasChanged) cb(); hooks[idx] = deps; idx++;}