许多使用现代 React 的前端开发人员不时地试图弄清楚为什么他们的组件在开发过程中渲染了两次。
其他人已经注意到这种行为,但他们认为这就是幕后React
运作的方式,而有些人甚至在React
官方存储库中打开了票证,将其报告为错误。
所以社区里肯定有一些关于这个的困惑😬
所有这些发生的原因是React.StrictMode
。
让我们深入研究一些真实的例子以复制这一点,然后首先调查为什么会发生这种情况。
我们可以从运行一个全新的CRA
安装开始:
npx create-react-app my-app && cd my-app
猛击
我们App.js
通过添加一个非常简单的console.log
语句来稍微调整一下:
function App() {
console.log('I render 😁');
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
</header>
</div>
);
}
反应 JSX
现在我们可以启动我们的应用程序yarn start
并http://localhost:3000
在浏览器中打开:
嗯,这条I render 😁
语句只打印了一次,所以我们不能用一个死的简单函数组件来重现双重渲染。
但是当我们使用 React 钩子并向我们的函数组件添加一些状态管理时会发生什么?
function App() {
const [clicks, setClicks] = React.useState(0);
console.log('I render 😁');
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<button onClick={() => setClicks(clicks => clicks + 1)}>
Clicks: {clicks}
</button>
</header>
</div>
);
}
反应 JSX
让我们再次检查浏览器:
我们来了!!所以它一开始渲染两次,然后每次我们点击我们添加的按钮时它都会渲染两次。
显然,React.useState
影响了我们组件关于重新渲染的行为。
生产包呢?为了检查这一点,我们需要先构建我们的应用程序,然后我们可以使用像serve
端口 3000这样的包来为它提供服务:
yarn build && npx serve build -l 3000
猛击
http://localhost:3000
再次在浏览器中打开:
呼!!!调试语句在开始时打印一次,每次单击按钮时都会打印一次。
正如我们所看到的,尽管我们通过使用React.useState
.
如上所述,原因是React.StrictMode
. 如果我们检查src/index.js
我们之前启动的应用程序中的文件CRA
,我们会看到我们的<App />
组件被它包裹了:
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
反应 JSX
显然,重新渲染的东西绝对不是错误,也不是与库的渲染机制有关的东西。相反是React
🤗提供的调试机制
React.StrictMode
是2018 年16.3.0版本中引入的包装器。起初,它仅应用于类组件,16.8.0之后它也应用于钩子。
如发行说明中所述:
React.StrictMode 是一个包装器,用于帮助为异步渲染准备应用程序
因此,它旨在帮助工程师避免常见的陷阱,并React
通过删除遗留 API 来逐步升级他们的应用程序。
这些提示对于更好的调试非常有帮助,因为库正在走向异步渲染时代,因此不时会发生重大变化。
多么有用,对吧?
我们从React.StrictMode
使用中获得的好处之一是它可以帮助我们检测渲染阶段生命周期中的意外副作用。
这些生命周期是:
constructor
componentWillMount
(或 UNSAFE_componentWillMount)componentWillReceiveProps
(或 UNSAFE_componentWillReceiveProps)componentWillUpdate
(或 UNSAFE_componentWillUpdate)getDerivedStateFromProps
shouldComponentUpdate
render
setState
更新程序函数(第一个参数)所有这些方法都被多次调用,因此避免在它们中产生副作用很重要。如果我们忽略这个原则,很可能会导致不一致的状态问题和内存泄漏。
React.StrictMode
不能立即发现副作用,但它可以通过有意调用两次某些关键函数来帮助我们找到它们。
这些功能是:
constructor
,render
和shouldComponentUpdate
方法getDerivedStateFromProps
方法setState
)useState
,useMemo
或useReducer
这种行为肯定会对性能产生一些影响,但我们不必担心,因为它只发生在开发中而不是生产中。
这就是为什么我们只能在开发中为使用React.useState
.
原文链接:https://codingdict.com/