一段时间以前,我们写了一篇文章有关我们即将升级我们遗留的生命周期方法,包含着我们慢慢的迁移的策略。在React 16.3.0这个版本中,为了慢慢迁移,我们增加了一些新的生命周期。我们也推荐了一些被长期期待的一些特性:一个官方的context api,一个 forwarding ref,一个ergonomic ref。
这么长时间以来,React一直提供了一个实验性的api context.尽管它是一个很有用的工具,我们还是不推荐使用它因为一些隐藏的问题。而且我们一直计划去用一个更好的api去替代它。
16.3这个版本引入了一个新的context api,它更加的高效,而且他支持各种静态类型检查和很深层次的更新。 这有一个例子来说明,你可以想象你注入了了一个“theme”变量去使用新的api
const ThemeContext = React.createContext("light")
class ThemeProvider extends React.Component{
state = {theme: 'light'}
render(){
return (
<ThemeContext.Provider value={this.state.theme}>
{this.props.children}
</ThemeContext.Provider/>
)
}
}
class ThemeButton extends React.Component{
render(){
return (
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
)
}
}
以前,react提供两种方式去管理refs,一个是字符串api,另一个是通过回调函数。尽管字符串这种方法是两种中最方便的,但是他有一些不完善的地方,所以我们官方建议是用回调去替代它。 16.3版本中提供了一个新的选项去管理refs,它和字符串方式一样便利,却没有它的缺点。
class MyComponent extends React.Component{
constructor(props){
super(props)
this.inputRef = React.createRef()
}
render(){
return <input type="text" ref={this.inputRef} />
}
componentDidMount(){
this.inputRef.current.focus()
}
}
通常,React组件是声明式的,但是有些时候有不可避免的会使用一些dom节点在组件的实例中。很通常的一些情况比如管理聚焦,选择或者动画。React提供了refs作为一种方式去解决这个问题。然而,组件封装提出了一些挑战。
例如,如果你用组件替代了,绑定在原先组件的ref属性值就开始指向了外层的包裹组件而不是DOM节点(在函数式的组件中将会是null),这就是被称赞的“application-level”组件就像评论组件一样需要被包装,它能够干扰叶子节点,例如FancyButon组件,他们的使用方式就和dom节点一样,或许他们还会暴露出他们的DOM节点。
Ref forwarding是一个新的特性,让许多组件能够接收ref,并且传给它的子组件。eg:
const FancyButton = React.forwardRef((props,ref) => {
<button ref={ref} className="FancyButton">
{this.prop.children}
</button>
})
const ref = React.createRef()
<FancyButton ref={ref}>click,/FancyButton>
用这种方式,组建可以将erf传递给DOM button,并且需要的话连接它,就像直接在使用一个dom组件。
当然,ref forwarding并不仅局限于向叶子组件渲染dom节点,如果你编写高阶组件的话,我们建议你用它自动的向那些被包裹的组件传递ref。
React组件的api已经很久没有改动了。然而,当我们添加了一些新特性(出错处理和异步渲染)之后,我们延伸出了这种模型尽管他并不是我们最初计划的。
例如,利用现有的api,很容易就可以阻止最初的渲染。这是因为有太多的过程去完成一次渲染。我们研究发现,出错行为的处理并没有被考虑进去,这样就会导致内存泄漏。而且现在的组件也让其他过程复杂化。
这些问题使得组件的生命周期被滥用。(componentWillMount,componentWillReceiveProps,componentWillUpdate)。而且令我们困惑的是这些错误经常发生在生命周期中。根据这些原因,我们决定使用一些更好的选择。
我们知道这些改变会影响很多已有的组件。因此,我们会尽可能慢慢的迁移,而且我们会提供一些别的方法。
我们为了放弃这些不安全的生命周期,我们提供了几个新的: