面试官:UNSAFE_componentWillxx 方法被废弃的原因是什么?
废弃 UNSAFE_componentWillMount 的原因
有一个常见的问题,有人问为什么不在 UNSAFE_componentWillMount
中写 AJAX 获取数据的功能,他们的观点是,UNSAFE_componentWillMount
在 render
之前执行,早一点执行早得到结果。但是要知道,在 UNSAFE_componentWillMount
中发起 AJAX 请求,不管多快得到结果也赶不上首次 render
,数据都是要在 render
后才能到达。
而且 UNSAFE_componentWillMount
在服务器端渲染也会被调用到(此方法是服务端渲染唯一会调用的生命周期函数。),你肯定不希望 AJAX 请求被执行多次,所以这样的 IO 操作放在 componentDidMount
中更合适。
尤其是在 Fiber 启用了异步渲染之后,更没有理由在 UNSAFE_componentWillMount
中进行 AJAX 请求了,因为 UNSAFE_componentWillMount
可能会被调用多次,谁也不会希望无谓地多次调用 AJAX 吧。
还有人会将事件监听器(或订阅)添加到 UNSAFE_componentWillMount
中,但这可能导致服务器渲染(永远不会调用 componentWillUnmount
)和异步渲染(在渲染完成之前可能被中断,导致不调用 componentWillUnmount
)的内存泄漏。
人们通常认为 UNSAFE_componentWillMount
和 componentWillUnmount
是成对出现的,但这并不能保证。只有调用了 componentDidMount
之后,React 才能保证稍后调用 componentWillUnmount
进行清理。因此,添加监听器/订阅的推荐方法是使用 componentDidMount
生命周期。
废弃 UNSAFE_componentWillReceiveProps 的原因
有时候组件在 props
发生变化时会产生副作用。与 UNSAFE_componentWillUpdate
类似,UNSAFE_componentWillReceiveProps
可能在一次更新中被多次调用。因此,避免在此方法中产生副作用非常重要。相反,应该使用 componentDidUpdate
,因为它保证每次更新只调用一次。UNSAFE_componentWillReceiveProps
是考虑到因为父组件引发渲染可能要根据 props
更新 state
的需要而设立的。新的 getDerivedStateFromProps
实际上与 componentDidUpdate
一起取代了以前的 UNSAFE_componentWillReceiveProps
函数。
废弃 UNSAFE_componentWillUpdate 的原因
有些人使用 UNSAFE_componentWillUpdate
是出于一种错误的担心,即当 componentDidUpdate
触发时,更新其他组件的 state
已经”太晚”了。事实并非如此。React 可确保在用户看到更新的 UI 之前,刷新在 componentDidMount
和 componentDidUpdate
期间发生的任何 setState
调用。
通常,最好避免这样的级联更新。当然在某些情况下,这些更新也是必需的(例如:如果你需要在测量渲染的 DOM 元素后,定位工具的提示)。不管怎样,在异步模式下使用 UNSAFE_componentWillUpdate
都是不安全的,因为外部回调可能会在一次更新中被多次调用。相反,应该使用 componentDidUpdate
生命周期,因为它保证每次更新只调用一次。
大多数开发者使用 UNSAFE_componentWillUpdate
的场景是配合 componentDidUpdate
,分别获取 rerender
前后的视图状态,进行必要的处理。但随着 React 新的 suspense
、time slicing
、异步渲染
等机制的到来,render
过程可以被分割成多次完成,还可以被暂停甚至回溯,这导致 UNSAFE_componentWillUpdate
和 componentDidUpdate
执行前后可能会间隔很长时间,足够使用户进行交互操作更改当前组件的状态,这样可能会导致难以追踪的 BUG。
React 新增的 getSnapshotBeforeUpdate
方法就是为了解决上述问题,因为 getSnapshotBeforeUpdate
方法是在 UNSAFE_componentWillUpdate
后(如果存在的话),在 React 真正更改 DOM 前调用的,它获取到组件状态信息更加可靠。
除此之外,getSnapshotBeforeUpdate
还有一个十分明显的好处:它调用的结果会作为第三个参数传入 componentDidUpdate
,避免了 UNSAFE_componentWillUpdate
和 componentDidUpdate
配合使用时将组件临时的状态数据存在组件实例上浪费内存,getSnapshotBeforeUpdate
返回的数据在 componentDidUpdate
中用完即被销毁,效率更高。
本文系作者 @K 原创发布在前端面试题大全站点。未经许可,禁止转载。
暂无评论数据