reactjs - 准系统 React 应用程序实例化应用程序并调用两次渲染
问题描述
使用npx create-react-app reactTwice
,我创建了一个准系统 React 应用程序,除了在控制台中记录某些操作之外什么都不做。这表明主 App 类被实例化了两次,并且它的render
方法被调用了两次,即使this.state
and的值this.props
没有改变。
我想了解为什么会这样。也许有一种方法可以避免它,也许发生这种情况有一个我需要考虑的具体原因。
您可以在此处找到此存储库。(请注意,在类似 jsFiddle 的站点上运行类似代码时不会发生此行为)。
这是启动应用程序的 index.js 脚本:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
console.log("ReactDOM.render() about to be called")
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
console.log("ReactDOM.render() was called")
这是生成App
类的脚本:
import React from 'react';
let instance = 0
export default class App extends React.Component {
constructor(props) {
super(props)
this.startTime = + new Date()
this.instance = ++instance
this.state = {}
this.imageError = this.imageError.bind(this)
console.log("App constructor (", this.instance, ")", this.getTime())
}
getTime() {
return + new Date() - this.startTime
}
runTimeOutMethod() {
console.log("runTimeOutMethod started (", this.instance, ")", this.getTime())
this.setState({ time: true })
console.log("runTimeOutMethod complete (", this.instance, ")", this.getTime())
}
imageError(event) {
console.log("DOM element added (", this.instance, ")", this.getTime())
}
render() {
console.log(
"render called (", this.instance, ")"
, this.getTime()
, this.state
, this.props
)
return (
<div className="App">
<img src="" alt="no src" onError={this.imageError} />
</div>
);
}
componentDidMount() {
console.log("componentDidMount started (", this.instance, ")", this.getTime())
this.setState({ mounted: true })
setTimeout(this.runTimeOutMethod.bind(this), 0)
console.log("componentDidMount complete (", this.instance, ")", this.getTime())
}
}
这是控制台中的示例输出。为了便于阅读,我添加了格式。
index.js: 5 ReactDOM.render() about to be called
App.js:14 App constructor ( 1 ) 0
App.js:14 App constructor ( 2 ) 0
App.js:36 render called ( 2 ) 1 {} {}
App.js:36 render called ( 2 ) 2 {} {}
App.js:52 componentDidMount started ( 2 ) 24
App.js:55 componentDidMount complete ( 2 ) 26
App.js:36 render called ( 2 ) 29 {mounted: true} {}
App.js:36 render called ( 2 ) 29 {mounted: true} {}
index.js:14 ReactDOM.render() was called
App.js:31 DOM element added ( 2 ) 46
App.js:24 runTimeOutMethod started ( 2 ) 47
App.js:36 render called ( 2 ) 48 {mounted: true, time: true} {}
App.js:36 render called ( 2 ) 48 {mounted: true, time: true} {}
App.js:26 runTimeOutMethod complete ( 2 ) 49
解决方案
此问题的所有症状都是由文件中的使用引起的<React.StrictMode>
,index.js
这是预期的行为。丹·阿布拉莫夫写道:
StrictMode 的全部目的是找出应该是纯的用户编写的函数实际上不是纯的...... [这不是错误,而是突变或副作用。是的,[调用两次] 是任意的,但我们发现它在实践中非常有效。
如果您将其更改为以下内容,则这些副作用将停止发生index.js
:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<>
<App />
</>,
document.getElementById('root')
);
在任何情况下,对构造函数和 to 的双重调用render
都不会在生产模式下进行。
推荐阅读
- css - Css 过渡动画 Firefox 和 Safari 不起作用
- azure - Azure ARM 模板部署任务无法从存储帐户下载模板(通过 Vnet/子网配置)
- javascript - 如何使用javascript调用异步函数直到条件为真?
- xpath - Power Automate 动态 xpath
- firebase - Firebase/Google Cloud Function 没有记录输出
- c++ - 在 CLion/Arch/CMake 项目中安装 IrrKlang
- storage - 运行脚本时的大 tmp 文件夹
- javascript - 使用 Axios Inteceptor 的 ModHeader 扩展
- r - 在 R 中发现不成功的传球导致失误(被对手拦截)
- python - 3D 散点图:多值图,按列着色