本文主要整合了自己在平常开发过程中遇到的一些 react 相关的问题的总结
2020/06/17 add 业务逻辑思考
2020/07/01 add react 生命周期钩子函数的变化
2020/07/05 add react this 的丢失
react this 丢失问题
react this 的丢失其实不赖 react,而是 js 的锅。
[转载|译] 为什么需要在 React 类组件中为事件处理程序绑定 this
React 绑定事件为什么会丢失this? 和如何解决绑定事件this指向问题
其实是以下这个问题的复现:即:当我们调用 b() 时,我们没有指定一个具体的上下文对象。这是一个没有所有者对象的纯函数调用。在这种情况下,getA() 内部的 this 值回退到默认绑定。现在这个 this 指向全局对象,在严格模式下,它指向 undefined。
let obj={
a:'tom',
getA(){
console.info(this.a);
}
};
obj.getA(); // tom
let b=obj.getA;
b(); // undefined
-
那这和 jsx 丢失 this 有什么关系呢?
- 我们知道jsx的原理本质上是React.createElement()
而React.createElement()有三个参数
第一个参数html标签的名字
第二个参数是传入的标签属性 传入的属性是以键值对的格式传入
第三个属性是节点要显示的内容
所以在第二个参数传入标签属性的时候 就相当于上面案例里的赋值 所以就这这时this就丢失了
- 我们知道jsx的原理本质上是React.createElement()
-
常见解决方法:
- 使用箭头函数:由于箭头函数的特性在箭头函数内的this即是指向当前对象的上下问 所以使用箭头函数可以解决
- 使用在绑定事件时使用bind(this)改变this指向
- 在constructor里使用bind()来改变事件对象的this指向
业务逻辑思考
首先描述一下开发中遇到的问题:我利用 ant-design 的 modal+form 做表单输入,首先 form 的 getFieldDecorator 监听的组件是唯一的也就是说 FormItem 应该是唯一单一组件,而我的业务场景中涉及动态添加及编辑单元格的操作,因此只能用子组件嵌入而脱离表单的动态控制====>此时由于用 state 控制此子表的值,要想在 modal cancel 或者更明确的说是任何一次关闭的时候清空表单就涉及对 state 的动态更新,同时鉴于 db 中也存有该子表的初始值因此子表的值同时受 props 以及动态改变的 state,让子表的 reset 变得不容易
React16新的生命周期函数getDerivedStateFromProps的使用,你也许并不需要派生状态【译】
解决方式: 使用 componentWillReceiveProps 对比 this.props 和 nextProps 的改变。
react 16 生命周期废弃与新增
以上这篇官方文档讲的十分清晰,对于开发过程中对派生 state 的使用以及常见的踩坑。常见场景,父组件可能每个 userId 不同,子组件是 input,切换父组件的 userId 此时 input 应该设置为相应的值,而同时子组件内部希望随时记录我们输入的 input
关于受控与非受控
名词“受控”和“非受控”通常用来指代表单的 inputs,但是也可以用来描述数据频繁更新的组件。用 props 传入数据的话,组件可以被认为是受控(因为组件被父级传入的 props 控制)。
数据只保存在组件内部的 state 的话,是非受控组件(因为外部没办法直接控制 state)。
关于新增
在很长一段时间内:生命周期函数 componentWillReceiveProps 是响应 Props 变化之后进行更新的唯一方式。
在 16 版本中提供了新的生命周期函数 getDerivedStateFromProps, 它的存在只有一个目的:让组件在 props 变化时更新 state。
对 componentWillReceiveProps getDerivedStateFromProps 派生 state 的滥用
最常见的误解就是 getDerivedStateFromProps 和 componentWillReceiveProps 只会在 props “改变”时才会调用。实际上只要父级重新渲染时,这两个生命周期函数就会重新调用,不管 props 有没有“变化”。所以,在这两个方法内直接复制(unconditionally)props 到 state 是不安全的。这样做会导致 state 后没有正确渲染。
更好的解决方式
完全可控的组件
- 删除子组件的 state,完全交由父组件控制 props 改变,可以通过父组件传给子组件 handleChange 方法。
有 key 的完全不受控的组件
即子组件设置 key,每次 key 变化都会重新渲染子组件,
使用 getDerivedStateFromProps
一个麻烦但是可行的方案是在 getDerivedStateFromProps 观察 userID 的变化
使用 refs
用实例方法强制重置内部状态
注: 以上描述起来可能比较抽象,可以更多的参考 references