React 的严格模式 (StrictMode) 有什么作用?
理解 React 严格模式 (StrictMode):它是什么,为什么需要它?
在日常的 React 开发中,我们常常会遇到一些难以追踪的问题,比如意料之外的组件行为、不易察觉的性能瓶颈,或是由旧版 API 埋下的技术债。为了帮助开发者在开发阶段就识别并修复这些潜在问题,React 提供了一个非常有用的工具——严格模式 (StrictMode)。
严格模式 (<React.StrictMode>) 本身不会渲染任何可见的 UI,它更像是一个“代码质检员”,专门为我们的应用开启额外的检查和警告。需要强调的是,这些检查只在开发模式下运行,不会影响生产环境的构建,因此我们可以放心使用。
接下来,我们将深入探讨严格模式主要关注哪些方面,以及它如何帮助我们写出更健壮、更现代的 React 代码。
识别不安全的生命周期方法
随着 React 的演进,一些早期的生命周期方法被认为存在潜在风险,尤其是在未来的并发渲染 (Concurrent Rendering) 模式下。这些方法可能会被多次调用,或者在不合适的时机中断,导致不可预测的行为,例如内存泄漏或状态不一致。
严格模式会重点标记以下这些不安全的生命周期方法:
componentWillMount(将被弃用,建议使用constructor替代)componentWillReceiveProps(将被弃用,建议使用staticgetDerivedStateFromProps替代)componentWillUpdate(将被弃用,建议使用getSnapshotBeforeUpdate替代)
当我们使用了这些方法时,控制台会输出警告,引导我们迁移到更安全、更现代的 API。这不仅是为了兼容未来的 React 版本,更是为了从根本上避免副作用带来的困扰。
警告废弃的 API 使用
除了生命周期方法,严格模式还会检查其他一些已被废弃或不推荐的用法。
旧版的 String Ref API:像this.refs.myRef这样的字符串引用方式存在一些问题,例如它无法被静态分析,且在处理动态子组件时显得笨拙。严格模式会推荐我们使用React.createRef()或回调形式的Refs (callback refs),这两种方式都更加灵活和可预测。旧版的 Context API:在现代React Context API(React.createContext)出现之前,存在一个实验性的Context API。它的API设计容易出错,且性能不佳。严格模式会检测并警告这种旧版API的使用,推动我们采用官方推荐的稳定方案。
检测意外的副作用
在 React 的理念中,渲染过程应该是“纯粹”的。这意味着对于相同的 props 和 state,渲染输出应该总是一致的,并且在这个过程中不应产生任何“副作用”(Side Effects),比如手动修改 DOM、发起网络请求或设置定时器。
为了帮助我们发现非纯粹的渲染逻辑,严格模式会故意重复调用某些函数,包括:
组件的
constructorrender方法setState的更新函数(updater functions)useState,useMemo,useReducer等Hooks
如果我们的代码在这些函数中包含了副作用,那么在严格模式下,这些副作用会被执行两次。这种“双重调用”机制就像一个压力测试,能立刻暴露那些隐藏在渲染过程中的不当操作,帮助我们将其移至更合适的地方,比如 useEffect 或 componentDidMount。
提醒废弃的 findDOMNode 用法
findDOMNode 曾被用来获取组件渲染出的底层 DOM 节点。但这种方式破坏了组件的封装性,使得父组件可以直接操作子组件的 DOM,导致重构困难。同时,在 React 的抽象模型中,一个组件也可能不会只渲染一个 DOM 节点(例如,使用 Fragment)。
因此,findDOMNode 正在被逐步废弃。严格模式会警告它的使用,并鼓励我们采用更现代的 Forwarding Refs 方案,将 Ref 从父组件安全地传递到子组件的 DOM 元素上,从而在保持封装性的同时实现必要的 DOM 操作。
如何启用严格模式?
启用严格模式非常简单,我们只需要用 <React.StrictMode> 标签包裹住需要检查的组件树即可。
我们可以将其应用于整个应用:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);也可以只针对应用中的特定部分,进行渐进式升级:
import React from 'react';
import { Header, Footer, Content } from './components';
function App() {
return (
<div>
<Header />
<React.StrictMode>
<Content />
</React.StrictMode>
<Footer />
</div>
);
}总结
总而言之,React 的严格模式是一个纯粹的开发辅助工具。它通过在开发环境中引入一系列额外的检查,帮助我们提前识别出代码中的不安全实践、潜在副作用和已被废弃的 API。
将严格模式集成到我们的工作流中,是一种低成本、高回报的投资。它不仅能提升当前代码的质量和稳定性,更能确保我们的应用为 React 未来的并发新特性做好准备,使项目在长期维护中保持健康。
