useState
-
最简单的 useState 用法是这样的:
function Counter() {var [count, setCount] = useState(0);return (<div><div>{count}</div><Button onClick={() => { setCount(count + 1); }}>点击</Button></div>); }
-
基于 useState 的用法,我们尝试着自己实现一个 useState:
function useState(initialValue) {var state = initialValue;function setState(newState) {state = newState;render();}return [state, setState]; }
-
这时我们发现,点击 Button 的时候,count 并不会变化,为什么呢?我们没有存储 state,每次渲染 Counter 组件的时候,state 都是新重置的。
自然我们就能想到,把 state 提取出来,存在 useState 外面。
```source-js
var _state; // 把 state 存储在外面function useState(initialValue) {_state = _state || initialValue; // 如果没有 _state,说明是第一次执行,把 initialValue 复制给它function setState(newState) {_state = newState;render();}return [_state, setState];
}
```
到目前为止,我们实现了一个可以工作的 useState,至少现在来看没啥问题。
接下来,让我们看看 useEffect 是怎么实现的。
useEffect
useEffect 是另外一个基础的 Hook,用来处理副作用,最简单的用法是这样的:
useEffect(() => {console.log(count);}, [count]);
我们知道 useEffect 有几个特点:
- 有两个参数 callback 和 dependencies 数组
- 如果 dependencies 不存在,那么 callback 每次 render 都会执行
- 如果 dependencies 存在,只有当它发生了变化, callback 才会执行
我们来实现一个 useEffect
let _deps; // _deps 记录 useEffect 上一次的 依赖function useEffect(callback, depArray) {const hasNoDeps = !depArray; // 如果 dependencies 不存在const hasChangedDeps = _deps? !depArray.every((el, i) => el === _deps[i]) // 两次的 dependencies 是否完全相等: true;/* 如果 dependencies 不存在,或者 dependencies 有变化*/if (hasNoDeps || hasChangedDeps) {callback();_deps = depArray;}
}