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