React踩坑总结::>_<::
2020/10/29
React的派生state问题
这个真的是个巨坑,主要是之前些写java C++之类的,在函数内保留复制参数值很常见,但在react内部,我们要尽量去避免这种,复制(mirror)props里的某些值给内部state。这也叫保守使用派生state的原则。
这里其实react官方文档里已经写得写的很清楚的,这里碎碎念一些自己的思考和理解。
这段时间写一个父->子->孙的组件,套了三层,而孙又要和父通信,因为臭习惯的问题,导致很多时候都会有父更新,子不更新或者孙不更新,爷孙三代并不会同时更新。出现这种React父子组件无法同步更新就是因为派生state的原因。
受控组件与非受控组件
这个概念也是react官方文档里有的,受控非受控的区别就在于,受控组件它的数据来源、展示来源是由props传来的,它的更新都是通过props的更改来的,而不是setState。
最开始接触这个概念的时候不太懂的,因为对react的渲染逻辑不太明白,不懂的话可以看react的生命周期,setState之后会进行更新调用
由于react组件的有挂载、更新、卸载,除了第一次挂载可以由didmount来控制数据变化,之后的更新都是自己state的改变,或者props的改变。这里就有三种模式了,自己更新自己的state,父组件传来的props改变了,自己或父组件的props改变了。
我个人感觉要么完全自己更新,除了第一个传来数据,之后的变化全由自己做主。或者要么完全受控,所有数据都来源自父组件。第三种混合的方式也可以,主要是要用上
static getDerivedStateFromProps(nextProps,nextState),
因为一般情况下,都是在constructor里面直接mirro父组件传过来的props的值,之后就很少会再重复更新了,因为之后state的值都不建议直接改,一般都用setState。而在使用state的过程中,通常又会在render里直接解构state的值,用解构的值来进行渲染,所以如果没有主动更改state的值的话,就算props改变了state里的值也不会改变。这就是我们说的派生state的缺点,因为你没办法及时地去更新他,所以一般解决派生state的问题的方法就是:不用|用getDerivedStateFromProps来比较props、更新state【用这个的话,要加判断语句,不然你更新state和更新props都会重新setState,就会死循环了】
static getDerivedStateFromProps(nextProps,nextState){
if(nextProps!==this.props){
this.setState({fromProps:nextProps.fromProps})
}
}
但是其实没啥必要,我们也说了保守使用派生state的原则。就记住一句话,能从props里拿的就不要用state函数,你不需要用派生state。要拿props里的数据就直接拿,不用非要保存在哪里,因为对于子组件来说props是没办法改变的。
纯函数
纯函数的概念就是,一个函数的输出只与它的参数相关,并且它并不会改变其他的值。输出只与它的参数有关这个是前提,如果有改变其他的值的话,这个叫做副作用。好多功能性函数它的目的就是副作用,比如在其中有一个setState,这个就不是纯函数了,因为它改变了别的值。举个栗子!
//这是一个纯函数
function add=(a,b)=>{
const x=5
return a+b+x
}
//这不是一个纯函数,因为x如果改变的话,输出的值也会改变
let x=5
function add=(a,b)=>{
return a+b+x
}
//这不是一个纯函数,因为改变了object的值,它有副作用
function add=(a,b,object)=>{
object.x=2
return a+b
}
简单的讲,纯函数就是单纯进行操作的函数,它并不会更改其他的数值,它最大的意义就是得到最后的return结果!所以纯函数也是一个很安全的函数。如果程序的大部分函数都是纯函数的话,调试修改起来会很方便。
我们在使用react的过程中最好把render函数作为一个纯函数,不要用它去改变某些值,它所做的就是,从别人那里拿来值,然后return你想要的结果,也就是一般不要再render里面加一些有的没有修改操作,就给值,给数据,返回就好了。值能从props拿,就从props拿,不能从props拿,再存在自己这里。这里就有一个之前没办法实时更新table表里内容的坑,主要原因是因为数据是从this.state里面拿的,而this.state又没有因为props的更改而更改。
react的生命周期
这个组件第一次加载到页面上的时候就要进行挂载(mount),挂载之后的所有变更基本上都是更新(update)了,react的生命周期有自己的改动,原本js里的部分周期不太适用在react里,他也给出了warning可能在之后会停用,所以用react就既来之则安之,顺应它的逻辑。
挂载的主要流程是:
constructor--->static getDerivedStateFromProps--->render--->componentDidMount
更新的主要流程(state和props改变的时候):
static getDerivedStateFromProps---->shouldComponenUpdate()//这个会返回true false默认是true---->render---->getSnapshotBeforeUpdate()//这个还不太懂---->ComponentDidUpdate
还有一个卸载,那个暂时还没考虑过性能的问题,还没怎么去想过。
20201103
学习过程中给自己的一些小tips
变量使用问题
这个坑自己之前是从没想过会这样的,主要是以前用java c++也没怎么考虑过深拷贝浅拷贝的问题,因为本来他俩本身这个概念就直接明显了当的讲出来了,用指针来指向地址,或者新建内存。
其实最大的问题就在于对let和const的不理解,因为一边学一边用,踩坑是自己这种学习模式常见情形。以前写代码的习惯被带到js之后,默认就把const类型当成不可更改的常量了,也不太理解非要用解构,数组展开这些东西
let和const
let和const定义的变量,除了六种基本类型Undefined、Null、Boolean、Number、String以及ojbect,前五种格式的const和let与java类似,let可以更改,const不可更改。
[]、