作者 Brian Vaughn 2018年3月29日
几天前, 我们 写了一篇关于对以前的生命周期方法进行更改的文章, 包括逐步迁移策略。 在React 16.3.0中, 我们正在添加一些新的生命周期方法来辅助迁移。我们还为长期被要求的功能引入了新的API: 一个官方的context API,一个转发的ref API和一个更符合人类使用的ref API.
官方 Context API
多年来,React仅提供了一个实验性的context API。尽管它是一个非常强大的API,但是,因为它固有问题以及我们打算用一个更好的API来替换这个实验的API,所以这个API一般不被推荐使用。
版本16.3引入了一个新的context API,它非常高效并且支持静态类型检查和深度更新。
注意
旧的context API将继续适用于所有React 1.6x版本,所以你将有足够的时间进行迁移。
下面是一个例子,说明如何使用新的context API注入一个『theme』:
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 ThemedButton extends React.Component { render() { return ( `<ThemeContext.Consumer>` {theme => `<Button theme={theme} />`} `</ThemeContext.Consumer>` ); } }
createRef
API
先前, React 提交供了两种管理refs的方法:传统的字符串形式API和回调函数API。尽管字符串引用API是两者中使用最方便的,但它也有几个缺点 ,所有我们官方的建议是使用回调函数形式代替它。
版本16.3增加了一个管理refs的新的选项,它提供了使用字符串形式ref的便利性而且没有任务缺点:
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(); } }
注意:
除了新的
createRef
API,Callback refs 将会继续得到支持。你没有必要替换掉你组件中的callback refs。它们稍微的更灵活一点,所以它们仍然是一个比较先进的功能。
forwardRef
API
高阶组件 (or HOCs) 是在组件间复用的代码的常用方法。基于上面的主题背景示例,我们中以创建一个HOC,它以属性的方式将当前『theme』进行注入:
function withTheme(Component) { return function ThemedComponent(props) { return ( `<ThemeContext.Consumer>` {theme => `<Component {...props} theme={theme} />`} `</ThemeContext.Consumer>` ); }; }
我们可以使用上面的HOC将组件直接连接到主体上下文,而无需直接使用 ThemeContext
。例如:
class FancyButton extends React.Component { buttonRef = React.createRef(); focus() { this.buttonRef.current.focus(); } render() { const {label, theme, ...rest} = this.props; return ( `<button {...rest} className={`${theme}-button`} ref={this.buttonRef}>` {label} `</button>` ); } } const FancyThemedButton = withTheme(FancyButton);// 我们可以渲染FancyThemedButton,就好像它是一个FancyButton// 它将会自动接收当前『theme』,// 同时HOC也会传递我们其它的props。`<FancyThemedButton label="Click me!" onClick={handleClick} />`;
HOCs通常将会把props传递给它们包裹着的组件。不幸的是, refs不会被传递。这意味着,如果我们使用FancyThemedButton
,我们将无法通过ref和FancyButton
进行连接,所以我们无法调用focus()
。
新的forwardRef
API解决了这个问题,它提供了一个方法来拦截ref
,并将它作为了普通的prop进行传递:
function withTheme(Component) { function ThemedComponent({forwardedRef, ...rest}) { return ( `<ThemeContext.Consumer>` {theme => ( // Assign the custom prop "forwardedRef" as a ref `<Component {...rest} ref={forwardedRef} theme={theme} />` )} `</ThemeContext.Consumer>` ); } // 注意第二个参数"ref"是由React.forwardRef提供的。 // 我们可以将它作为变通的props传递给ThemedComponent,例如 "forwardedRef" // 然后它可以被连接到这个组件。 return React.forwardRef((props, ref) => ( `<ThemedComponent {...props} forwardedRef={ref} />` )); }// 在这里,我们假设FancyButton已经被导入到当前上下文const FancyThemedButton = withTheme(FancyButton);// 通过Referenace API创建一个ref,const fancyButtonRef = React.createRef();// fancyButtonRef 现在指向 FancyButton`<FancyThemedButton label="Click me!" onClick={handleClick} ref={fancyButtonRef} />`;
组件生命周期变更
React类组件的API已经有好多年了,而且几乎没有变化。但是,当我们添加对更高级功能的支持时(比如错误边界和即将到来的异步渲染模式),我们会以不是我们想要的方式来扩展此模型。
例如,使用当前的API,可以很容易的阻止非必要的逻辑进行初始渲染。部分原因是因为完成某项任务的方式太多,而且哪一个最好也不清楚。我们已经观察到错误中断的处理行通常不被考虑在内,并且可能导致内存泄漏(它会影响到即将到来的异步渲染模式)。目前的类组件API也使其他工作复杂化,就像我们在原型化React编译器方面的工作一样。
这些问题在组件生命周期(componentWillMount
, componentWillReceiveProps
, and componentWillUpdate
)的一个子集中更加的恶化。这些也恰好是造成React社区最混乱的生命周期问题。出于这些原因的考虑,我们将会降低这些方法的使用,转而使用更好的方法代替。
我们意识到这些变更将会影响到现有的组件。因此,迁移路径将会是渐进式的,并且会提供补救措施。(在Facebook上,我们维护了超过50,000个React组件。 我们也依赖于一个渐进的发布周期! )
注意:
弃用警告将在未来的16.x版本中启用,但旧版生命周期将继续运行至17.x版。
即使在17.x版中,仍然可以使用它们,但它们会以『UNSAFE_』为前缀被重命名,以表明它们可能会引起问题。我们还准备了一个自动化的脚本来在现有代码中对它们重新命名。
除了摒弃不安全的生命周期外,我们还增加了一些新的生命周期:
getDerivedStateFromProps
是一个比较安全的方法来替代以前componentWillReceiveProps
.getSnapshotBeforeUpdate
用于更安全的读取属性,比如在更新之前获取DOM。
StrictMode
Component
StrictMode
是一个突出显示应用潜在问题的工具。像Fragment一样,StrictMode不会呈现任何可见的UI。它会为子组件作额外的检查并发出警告。
注意:
StrictMode
检查仅仅运行在开发模式下; 它们不影响生产构建。
尽管在严格模式下不可能捕获所有的问题(例如:某些类型的突变),但在它在大多数情况下还是很有用的。如果你在严格模式下看到警告,这些东西可能会引起异步渲染的错误。
在16.3版中,StrictMode
提供以下帮助:
识别不安全的生命周期组件
对使用字符串ref API进行警告
检测潜在副作用
随着未来React的发版,将会添加更多的功能。
共同学习,写下你的评论
评论加载中...
作者其他优质文章