React 16.6.X版本的更新功能
React发布了16.6版本,在此版本中带来了一些非常有用的新特性。主要的新特性包括:
React.lazy()
React.memo()
static contextType()
static getDerivedStateFromError()
StrictMode下的新提醒
下面一起来看看吧
lazy
新版本的更新让人期待的功能之一肯定就是lazy
功能啦,搭配发布了一个Suspense
组件,用来配合render
方法内部的异步操作的,让我们先来看一下lazy
的用法
import React, { lazy, Suspense } from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
);
}
做过code-splitting
的同学能闻到熟悉的味道。以前我们要用第三方包或者自己处理异步过程,现在,React原生支持啦,而且你可以把异步的过程直接扔到render
方法里面,就跟写普通组件一样,而且可以方便得通过Suspense
组件来提供fallback
然而这并不仅仅Suspense
的唯一用处,事实上这次React正式开放Suspense
组件代表着所有异步的操作都可以在render
方法里面做了,其实我很意外,我以为正式开放肯定要等到17版本
那么异步操作还能做啥?如果同学们看过年初Dan在冰岛的分享,应该就知道,Suspense
能够让我们加载数据的操作变得异常简单。没看过的同学可以看这里,现在npm上也有一个包提供数据加载的功能了,simple-cache-provider,但是现在还不要在正式环境使用他哦。
关于这部分如何实现的,我会在之后的源码分析上详细讲解,有兴趣的同学可以关注我。
React.memo
ClassComponent
可以通过继承类PureComponent
或者实现shouldComponentUpdate
来主动判断组件是否需要重新渲染,以此来提高性能,但是FunctionalComponent
到目前为止没有类似的功能。
所以今天React发布了React.memo
方法,来实现类似PureComponent
的功能,即浅比较props
是否有变化,如果没有变化,就不重新渲染当前组件
const FunctionalComponent = React.memo((props) => {
// only render if props change
})
static contextType
在React16.3中提供了我们一个标准的用于替代老的context
的API,也就是React.createContext
,然后通过context.Provider
和context.Consumer
来传递值,这种方式消除了老的context
API性能低下的问题,这个问题我在之前也有详细分析,感兴趣的同学可以看这里,而且老的API代码量很多,所以下个大版本React会移除老的API。
但是在让生态插件升级到新的API的过程中,有人提出在ClassComponent
中用新的API很麻烦(???没感觉啊),所以React提供了一种在ClassComponent
中使用新API的方法
import React, { Component } from 'react';
const context = React.createContext('defaultValue')
const ProviderComp = ({ children }) => (
<context.Provider value="provider">
{children}
</context.Provider>
)
class ConsumerComp extends Component {
static contextType = context
componentDidMount() {
console.log(this.context)
}
render() {
return (
<p>{this.context}</p>)
}
}
class App extends Component {
render() {
return (
<ProviderComp>
<ConsumerComp />
</ProviderComp>);
}
}
通过声明static contextType = context
,让ClassComponent
可以订阅最近的一个context provider
,注意这里contextType
是固定声明,换成别的名字都不行。如果ConsumerComp
不在Provider
的子树中,那么会使用defaultValue
class App extends Component {
render() {
return (
<div>
<ProviderComp />
<ConsumerComp />
// show default value
</div>
);
}
}
这也是为了提高React的整体性能,移除老旧API做努力。
static getDerivedStateFromError()
在发布Error Boundaries
的时候,React提供了一个新的生命周期方法componentDidCatch
,在捕获到错误的时候会触发,你可以在里面修改state
以显示错误提醒的UI,或者将错误信息发送给服务端进行log
用于后期分析。但是这里有个问题,就是在捕获到错误的瞬间,React会在这次渲染周期中将这个组件渲染为null
,这就有可能导致他的父组件设置他上面的ref
获得null
而导致一些问题,所以现在提供了这个方法。
这个方法跟getDerivedStateFromProps
类似,唯一的区别是他只有在出现错误的时候才触发,他相对于componentDidCatch
的优势是在当前的渲染周期中就可以修改state
,以在当前渲染就可以出现错误的UI,而不需要一个null
的中间态。
而这个方法的出现,也意味着以后出现错误的时候,修改state
应该放在这里去做,而后续收集错误信息之类的放到componentDidCatch
里面。
StrictMode下的新提醒
StrictMode
是用来提醒开发者用了即将被废弃的API的,像componentWillMount
这些声明周期都会提醒,这次新加了两个API的提醒,ReactDOM.findDOMNode()
,和老的context api
。