为什么全局变量在 React 中被执行了两次
Why is global variable executed twice in React
我是前端开发和学习 React 的新手。现在我正在尝试构建一个 hello-world 项目。
执行 npx create-react-app myapp
后,我得到了一个初始 React 项目,我只是在文件 App.js
.
中编码
import React, {useState} from 'react';
var counter = 0;
function App() {
const [counter2, setCount] = useState(0);
const increment = () => {
setCount(counter2 + 1);
};
return(
<div>
<button onClick= {increment}>Increment</button>
<h1>{counter++}</h1> // 1, 3, 5, 7... WHY???
<h1>{counter2}</h1> // 0, 1, 2, 3...
</div>
);
}
export default App;
执行npm start
后,我得到了我的索引页,它包含三个部分:一个按钮和两个数字。
令我惊讶的是,当我单击该按钮时,counter2
按预期增加,但 counter
增加了两次。意思是一直点击按钮会得到如下结果:
1 0
、3 1
、5 2
...
为什么全局变量counter
是两两递增,而不是一递增?
另外,React State和普通全局变量有什么区别?
当你在 <React.StrictMode>
中包装一个组件时,它会 运行 某些函数两次,其中一次是你的功能组件的函数体:
This is done by intentionally double-invoking the following functions:
... Function component bodies
这只在开发模式下完成,这样做的目的是帮助您捕捉项目中的副作用。
虽然您的组件似乎只被执行一次,但在您的功能组件中放置一个 console.log()
每次状态更改只会 运行 一次。这是因为,从 React 17 开始,他们已将 console.log 方法更新为 not log on the second invocation of your function:
Starting with React 17, React automatically modifies the console
methods like console.log() to silence the logs in the second call to
lifecycle functions
但是,通过保存对 console.log
方法的引用并使用它来执行您的日志,可以解决此问题。这样做可以让您看到您的组件被执行了两次:
const log = console.log;
function App() {
const [counter2, setCount] = useState(0);
const increment = () => {
setCount(counter2 + 1);
};
log("Rendering, counter is:", counter);
return(
<div>
<button onClick= {increment}>Increment</button>
<h1>{counter++}</h1>
<h1>{counter2}</h1>
</div>
);
}
上面在组件挂载时会输出如下,说明函数体是运行ning了两次:
Rendering, counter is: 0
Rendering, counter is: 1
如果你删除 <React.StrictMode>
组件,那么每次渲染计数器都会增加 1,因为 React 将不再重复调用你的功能组件体,你的组件体只会被调用一次:
ReactDOM.render(<App />, document.getElementById('root'));
就全局变量与状态而言,主要区别已在 中指出。也就是说,当您使用 setMethodName()
更新您的状态时,您将导致您的组件主体重新渲染,这在您更新普通变量时不会发生,因为 React 不会意识到对其所做的更改。
我是前端开发和学习 React 的新手。现在我正在尝试构建一个 hello-world 项目。
执行 npx create-react-app myapp
后,我得到了一个初始 React 项目,我只是在文件 App.js
.
import React, {useState} from 'react';
var counter = 0;
function App() {
const [counter2, setCount] = useState(0);
const increment = () => {
setCount(counter2 + 1);
};
return(
<div>
<button onClick= {increment}>Increment</button>
<h1>{counter++}</h1> // 1, 3, 5, 7... WHY???
<h1>{counter2}</h1> // 0, 1, 2, 3...
</div>
);
}
export default App;
执行npm start
后,我得到了我的索引页,它包含三个部分:一个按钮和两个数字。
令我惊讶的是,当我单击该按钮时,counter2
按预期增加,但 counter
增加了两次。意思是一直点击按钮会得到如下结果:
1 0
、3 1
、5 2
...
为什么全局变量counter
是两两递增,而不是一递增?
另外,React State和普通全局变量有什么区别?
当你在 <React.StrictMode>
中包装一个组件时,它会 运行 某些函数两次,其中一次是你的功能组件的函数体:
This is done by intentionally double-invoking the following functions:
... Function component bodies
这只在开发模式下完成,这样做的目的是帮助您捕捉项目中的副作用。
虽然您的组件似乎只被执行一次,但在您的功能组件中放置一个 console.log()
每次状态更改只会 运行 一次。这是因为,从 React 17 开始,他们已将 console.log 方法更新为 not log on the second invocation of your function:
Starting with React 17, React automatically modifies the console methods like console.log() to silence the logs in the second call to lifecycle functions
但是,通过保存对 console.log
方法的引用并使用它来执行您的日志,可以解决此问题。这样做可以让您看到您的组件被执行了两次:
const log = console.log;
function App() {
const [counter2, setCount] = useState(0);
const increment = () => {
setCount(counter2 + 1);
};
log("Rendering, counter is:", counter);
return(
<div>
<button onClick= {increment}>Increment</button>
<h1>{counter++}</h1>
<h1>{counter2}</h1>
</div>
);
}
上面在组件挂载时会输出如下,说明函数体是运行ning了两次:
Rendering, counter is: 0
Rendering, counter is: 1
如果你删除 <React.StrictMode>
组件,那么每次渲染计数器都会增加 1,因为 React 将不再重复调用你的功能组件体,你的组件体只会被调用一次:
ReactDOM.render(<App />, document.getElementById('root'));
就全局变量与状态而言,主要区别已在 setMethodName()
更新您的状态时,您将导致您的组件主体重新渲染,这在您更新普通变量时不会发生,因为 React 不会意识到对其所做的更改。