React 16 对比 15 的变更和要注意的点
React 16 对比 15 的变更和要注意的点
React 16 核心变更
1. Fiber 架构:更高效的更新机制
React 16 的核心变更是引入了 Fiber 架构,它完全重写了 React 的 Reconciler(协调器),主要带来了以下优势:
- 异步渲染:渲染任务可被打断,提高高优先级任务的响应速度。
- 更细粒度的更新:组件更新拆分成小任务,避免长时间阻塞主线程。
2. 生命周期方法的调整
React 16 废弃了一些生命周期方法,并引入了新的替代方案。
React 15 生命周期 | React 16 变更 |
---|---|
componentWillMount | 用 constructor 或 componentDidMount 替代 |
componentWillReceiveProps | 用 getDerivedStateFromProps 替代 |
componentWillUpdate | 用 getSnapshotBeforeUpdate 替代 |
影响:
- 如果你的代码依赖
componentWillReceiveProps
处理 props 变化,请使用getDerivedStateFromProps
。 - 如果你在
componentWillUpdate
里获取 DOM 快照,请改用getSnapshotBeforeUpdate
。 - 如果你在
componentWillMount
里做副作用操作(如 API 请求),请改到componentDidMount
。
示例(getDerivedStateFromProps
):
1
2
3
4
5
6
7
8
class MyComponent extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.value !== prevState.value) {
return { value: nextProps.value };
}
return null;
}
}
3. Error Boundaries(错误边界)
React 16 允许我们使用 Error Boundaries 来捕获子组件的错误,防止整个应用崩溃。
** 新增方法:**
componentDidCatch(error, info)
static getDerivedStateFromError(error)
示例(错误边界组件):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error("Caught error: ", error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>发生错误</h1>;
}
return this.props.children;
}
}
注意点:错误边界 只能捕获子组件的渲染错误,但不会捕获 事件处理器、异步代码(如 setTimeout
)、服务端渲染(SSR)等错误。
其他新特性与优化
1. React Portals(跨层级渲染)
在 React 15 中,组件的渲染层级受限于组件树,而在 React 16 中,可以使用 ReactDOM.createPortal
将组件渲染到任意 DOM 位置。
示例(创建 Modal 组件):
1
2
3
4
ReactDOM.createPortal(
<div className="modal">Hello Portal</div>,
document.getElementById("modal-root")
);
常用场景:模态框、全屏弹窗等。
2. 服务器端渲染(SSR)优化
React 16 提供了 renderToNodeStream
,相较于 React 15 的 renderToString
,可以 流式渲染 HTML,提高 SSR 性能。
示例(SSR 流式渲染):
1
2
const stream = ReactDOMServer.renderToNodeStream(<App />);
stream.pipe(res);
This post is licensed under CC BY 4.0 by the author.