区别
- 类组件有生命周期、this组件实例、state内部状态,函数组件都没有但会被更新并挂载
- hooks适合跨组件复用,轻量
生命周期区别
- useState:用于定义组件的state,类似this.state
- useEffect:依赖触发,异步执行,不会等待DOM渲染完成后实行(类组件的componentDidMount、componentDidUpdate、componentWillUnmount)
- useContext:获取context对象
- useReducer:不是持久化存储,组件销毁而销毁,配合useContext使用
- useCallback:缓存回调函数,避免传入的回调每次都是新的函数实例而导致依赖组件重新渲染
- useMemo:用于缓存传入的props,避免依赖的组件每次都重新渲染
- useRef:获取组件的真实节点
- useLayoutEffect:DOM更新渲染后触发,属于同步操作,可以获取更新后的state
- 自定义钩子(useXxx)
useEffect
- 有两个参数 callback 和 dependencies 数组
- 如果 dependencies 不存在,那么 callback 每次 render 都会执行
- 如果 dependencies 存在,只有当它发生了变化, callback 才会执行
对比
useEffect(() => {
console.log(count);
}, [count]);
// 实现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;
}
}
Q:为什么第二个参数是空数组,相当于 componentDidMount ?
A:因为依赖一直不变化,callback 不会二次执行
React 中是通过类似单链表的形式,通过 next 按顺序串联所有的 hook
react hoos原理:github.com/brickspert/…