React Hooks也学习使用了一段时间,但是脑海中还没有形成自己的知识体系,笔记也乱七八糟。重新回顾整理下笔记吧。
本文只是学习笔记,是对看过的多篇博客文档的学习总结,在文章最后附有原文链接。当然还是看大佬们的原文更好哈,我这只是方便自己的学习记忆。
Class Component存在的问题
(点击展开看详细)
👇1. 组件复用问题
组件数据共享:单向数据流Flux解决。
组件复用:之前的类组件与Render Props和Higher Order Component(HOC)结合存在缺陷
HOC带来的问题有:
嵌套地狱,每一次HOC调用都会产生一个组件实例
包裹太多层级之后,可能会带来props属性的覆盖问题
Render Props的问题:
Render Props本质是基于闭包实现的,大量用于组件复用将不可避免地引入了回调地狱问题
丢失了组件的上下文,因此没有this.props属性,不能像HOC那样访问this.props.children
👇2. JavaScript中class的缺陷
类组件容易造成this指向报错问题
编译大小和性能都不够好
Javascript实现的类,没有类似Java/C++多继承的概念,类的逻辑复用是个问题
👇3. 函数组件功能缺失
函数式组件本身是无状态组件,不能脱离类组件使用。
自身不能状态处理,需要依赖props传入的handle来响应状态变更。Hooks解决了这个问题。
Hooks的使用
注意:只能在函数式组件里调用Hooks API。
useState
const [state, setState] = useState(initialState);
作用:返回一个状态以及能修改这个状态的setter,一旦mount之后只能通过这个setter修改这个状态。
setter可以改变组件的状态,并且引起组件re-render。
问:为什么必须在函数组件顶部作用域调用Hooks API?
在类组件中,state是一个对象,对应FiberNode的memoizedState属性,调用
setState()时更新memoizedState即可。
但是在函数组件中,Hook以链表形式进行存储。Hook API调用会产生一个对应的Hook实例
并追加到Hooks链,但是返回给组件的是state和对应的setter,re-render时框架并不知
道这个setter对应哪个Hooks实例,它会从第一行代码开始按顺序执行整个Hooks链。而且
首次render之后,只能通过useState返回的dispatch修改对应Hook的memoizedState,
只有在顶层调用才能保证各个Hooks的执行顺序。
问:useState hook如何更新数据?
state通过dispatchAction函数更新,它会生成一个update挂载到Hooks队列上面,并提
交一个React更新调度,后续的工作和类组件一致。理论上可以同时调用多次dispatch,
但只有最后一次会生效(因为React会依次执行hook对象上的整个更新队列,last指针指
向最后一次update的state)。
在update阶段,state改变、父组件re-render等都会引起组件状态更新,但initialState并没有用到。
useState更新数据和setState不同:setState会与旧状态合并,只需把更改的部分传
进去,但是useState则是直接覆盖。
useState hook更新过程
function App() {
const [n1, setN1] = useState(1);
const [n2, setN2] = useState(2);
const [n3, setN3] = useState(3);
useEffect(() => {
setN1(10);
setN1(100);
}, []);
return (<button onClick={() => setN2(20)}>click</button>);
}
setState返回的setter执行会导致re-render.
首次渲染时,n1,n2,n3的state值分别是1,2,3。
第一次重渲染,执行useEffect内部的setter,仅最后一次生效,n1值为100.
点击button进行第二次重渲染时,n2值为20.
未完待续,整理半天useState都没弄完,我是蜗牛吧/(ㄒoㄒ)/~~如有错误恳请批评指正。