生命就是数据处理的过程。那么认知升级,就是某部分算法迭代和优化的过程。
—《未来简史》
V16.0
返回结构的升级
v15版本要求返回的必须都是一个html元素;
v16版本规定返回的拥有5类大全:React elements, 数组和Fragments,Portal,String/numbers,boolean/null;
Error Boundary
v15版本的容错机制不突出,一旦渲染过程出现问题,会crash掉整个页面,显示白屏;
v16版本的边界错误很优秀,也就是说边界错误用于捕获子组件树(组件在树中比他低级的组件树)的JS异常,log一个错误并展示一个回退的UI;捕获范围:渲染期内,生命周期内,整个组件树的构造函数内;
比如:单独给出的一个组件来抛出了异常,需要单独检测,如果是在其他组件内部抛错,在条件后面加上 throw new Error(‘crashed!’),组件内直接引入抛出组件就可以了,demo可以直接copy官网get;
捕获组件可以在errorInfo
信息中给出组件的错误信息;
捕获盲区:
- 不能捕获事件函数内部的错误,因为捕获范围发生在渲染阶段内,因此事件函数内部的容错可以使用trycatch来get;
- 不能捕获异步请求中的数据,不能捕获服务端的渲染数据;
- 不能捕获边界组件自己出现的错误;
react portals
portal的出现可以独立于页面的dom层级像组件一样使用,可以保证不在父组件之内而且是显示在独立于原来app在外的同层级组件。
在使用的时候 页面上直接引入DOM就OK了;
优化SSR
- 生成简洁的HTML,可读性更强;
- 宽松的客户端一致性体验:
v15:会将SSR的结果与客户端生成的做一个个字节的对比校验 ,一点不匹配发出waring同时就替换整个SSR生成的树。v16:对比校验会更宽松一些,比如,v16允许属性顺序不一致,而且遇到不匹配的标签,还会做子树的修改,不是整个替换。
注意点: v16不会自动fix SSR 属性跟client html属性的不同,但是仍然会报waring,所以我们需要自己手动去修改。 - v16服务端渲染速度更快一些
因为v15下 server client都需要生成vDOM,但是其实在服务端, 当我们的改动触及render的时候,生成的vDom就会被立即抛弃掉, 所以在server端生成vDom是没有意义的。对于生命周期来说:React16由于异步渲染等特性会让之前的一些方法如componentWillMount变得不够安全高效逐步废弃。
V16.2
Fragement
render里可以通过Fragement直接返回多个组件,该组件会自动添加key值,使用者不用担心唯一键值的问题。
V16.3
部分生命周期变更
由于异步渲染的改动,所以componentWillReceiveProps,componentWillUpdate,componentWillMount 三个生命周期可能要抛弃使用。
但是目前还是基于最小改变的基础上改变,在V17版本中,只能在前面加"UNSAFE_" 的前缀来使用。
context API
context 就是可以使用全局的变量,不需要一层层pass props下去,比如主题颜色;
什么场景下需要用context? 一些相同的data需要被大多的component用到,并且还是在不同的层级里。 一般用于主题,存储数据等。
context 是我初识react升级版本之后的缺失点,因此需要开一篇新文记录我心中的context来记录~
createRef
使用新的 React.createref() 函数使 ref 创建变得更容易:
// 在 class 中声明
third = React.createRef();
// 或者在 constructor 中声明
this.third = React.createRef();
// 在 render 函数中:
<input type="text" defaultValue="Third" ref={this.third} />;
// 获取 ref
this.third.current;
// 获取 input 的 value
this.third.current.value;
forwardRef API
使用场景:父组件需要将自己的引用传给子组件。如果你写的是一个高阶组件,那么推荐使用forwardAPI 将ref传给下面的component。
const testRef = React.forwardRef((props,ref)=>{
...
})
V16.4
今天 React 16.4 发布了, getDerivedStateFromProps 的触发时机有所改动——原本在父组件重新渲染它时才会触发 getDerivedStateFromProps ,现改为只要渲染就会触发,包括自身 setState 。这一变化进一步地区分了该方法与 componentWillReceiveProps ,更适合异步渲染。
getDerivedStateFromProps
- 这个函数会在render函数被调用之前调用,包括第一次的初始化组件以及后续的更新过程中,每次接收新的props之后都会返回一个对象作为新的state,返回null则说明不需要更新state。
- 该方法主要用来替代componentWillReceiveProps方法,willReceiveProps经常被误用,导致了一些问题,因此在新版本中被标记为unsafe。willReceiveProps的常见使用方法是根据传进来的属性值判断是否要load新的数据。但这个方法的一个问题是外部组件多次频繁更新传入多次不同的 props,而该组件将这些更新 batch 后仅仅触发单次自己的更新,这种写法会导致不必要的异步请求。
- 那么,相比下来getDerivedStateFromProps配合componentDidUpdate的方式只在更新触发后请求数据,相比下来更节省资源。写法如下:
class ExampleComponent extends React.Component {
state = {
isScrollingDown: false,
lastRow: null,
};
static getDerivedStateFromProps(nextProps, prevState) {
// 不再提供 prevProps 的获取方式
if (nextProps.currentRow !== prevState.lastRow) {
return {
isScrollingDown: nextProps.currentRow > prevState.lastRow,
lastRow: nextProps.currentRow,
};
}
// 默认不改动 state
return null;
}
componentDidUpdate() {
// 仅在更新触发后请求数据
this.loadAsyncData()
}
loadAsyncData() {/* ... */}
}
注意getDerivedStateFromProps是一个static方法,意味着拿不到实例的this
getSnapshotBeforeUpate
该方法的触发时间为update发生的时候,在render之后dom渲染之前返回一个值,作为componentDidUpdate的第三个参数。该函数与 componentDidUpdate 一起使用可以取代 componentWillUpdate 的所有功能,比如以下是官方的例子:
class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the scroll position so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// If we have a snapshot value, we've just added new items.
// Adjust scroll so these new items don't push the old ones out of view.
// (snapshot here is the value returned from getSnapshotBeforeUpdate)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}
引用掘金例子来对以上3个关联生命周期总结:
class Example extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
// 这一生命周期方法是静态的,它在组件实例化或接收到新的 props 时被触发
// 若它的返回值是对象,则将被用于更新 state ;若是 null ,则不触发 state 的更新
// 配合 `componentDidUpdate` 使用,这一方法可以取代 `componentWillReceiveProps`
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// 该方法在实际改动(比如 DOM 更新)发生前的“瞬间”被调用,返回值将作为 `componentDidUpdate` 的第三个参数
// 配合 `componentDidUpdate` 使用,这一方法可以取代 `componentWillUpdate`
}
componentDidUpdate(props, state, snaptshot) {
// 新增的参数 snapshot 即是之前调用 getSnapshotBeforeUpdate 的返回值
}
}
……暂时先写到这里啦
对于生命周期的解释,比较好的?还有掘金
参考链接:https://mp.weixin.qq.com/s/Ldi2LOENuvF2HKoWvMFoBg