使用 create-react-app 创建的 React 应用程序无故递增模块范围的变量
React application created using create-react-app increments module-scoped variable without reason
我有一个使用 create-react-app 创建的 React 应用程序。我正在测试一些东西并创建了以下代码:
import React, {useState} from "react";
var a = 1;
function useForceUpdate() {
const [state, setState] = useState(true);
return [() => setState(!state)];
}
function App() {
const [forceUpdate] = useForceUpdate();
a++;
console.log(a);
return (
<div onClick={forceUpdate}>
{a}
</div>
);
}
export default App;
出于某种原因,它以 3 的值开始,每次单击它都会递增 2 或 3,而不是 1,但这只发生在我现有的项目中,该项目具有其他库,例如酶、react-hooks -测试库和其他。在一个只更改了 App.js 代码的新项目中,它从 3 开始,并始终在单击时恰好递增 2。我在 codepen 上试过它,它以 2 的值开始,并按应有的方式递增 1。这是代码笔(将此处的.js文件:https://reactjs.org/redirect-to-codepen/hello-world替换为以下代码):
var a = 1;
function useForceUpdate() {
const [state, setState] = React.useState(true);
return [() => setState(!state)];
}
function App() {
const [forceUpdate] = useForceUpdate();
a++;
console.log(a);
return (
<div onClick={forceUpdate}>
{a}
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
在 codesandbox 上(只需将其中的 .js 文件替换为下面提供的文件:https://codesandbox.io/s/new?file=/src/App.js)它再次以值 3 开始,每次递增 2:
import React from "react";
var a = 1;
function useForceUpdate() {
const [state, setState] = React.useState(true);
return [() => setState(!state)]
}
function App() {
const [forceUpdate] = useForceUpdate();
a++;
console.log(a);
return (
<div onClick={forceUpdate}>
{a}
</div>
);
}
export default App;
为什么他们的行为如此不同?
发生这种情况是因为 React's Strict Mode
。React 的严格模式会双重调用某些函数,以识别您的应用程序中任何不需要的副作用。您可以在这里阅读更多相关信息:React Strict Mode
现在,如果您转到应用程序的 index.js
文件,您会看到该应用程序已被严格模式包装。 codesandbox 中 index.js 文件的情况类似。
例如,
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
rootElement
);
但是在 codepen 的情况下,代码没有任何 StrictMode 包装因此,它只添加一次到 a.
这是关于将文件分成模块,但我无法解释幕后到底发生了什么。最有可能的是,以某种方式连接模块只是读取文件,而不是将其代码包含在主代码中。这将增加变量。
您可以轻松查看:
- 第一种情况 - 在单独的文件(模块)中创建组件并将其导入根目录 index.js
- 第二种情况 - 在一个文件(模块)中通过调用 ReactDOM.render 创建组件
并在组件外添加console.log
- 在第一种情况下 - 您将看到 3 个日志,2 个位于组件外部,1 个位于组件内部。
- 第二种情况 - 2 根原木,1 根在外面,1 根在里面
当然在第一种情况下它以 3 开头,因为您使用的是捆绑代码。
但在我看来,在组件代码或状态管理器之外定义组件更改变量是错误的
我有一个使用 create-react-app 创建的 React 应用程序。我正在测试一些东西并创建了以下代码:
import React, {useState} from "react";
var a = 1;
function useForceUpdate() {
const [state, setState] = useState(true);
return [() => setState(!state)];
}
function App() {
const [forceUpdate] = useForceUpdate();
a++;
console.log(a);
return (
<div onClick={forceUpdate}>
{a}
</div>
);
}
export default App;
出于某种原因,它以 3 的值开始,每次单击它都会递增 2 或 3,而不是 1,但这只发生在我现有的项目中,该项目具有其他库,例如酶、react-hooks -测试库和其他。在一个只更改了 App.js 代码的新项目中,它从 3 开始,并始终在单击时恰好递增 2。我在 codepen 上试过它,它以 2 的值开始,并按应有的方式递增 1。这是代码笔(将此处的.js文件:https://reactjs.org/redirect-to-codepen/hello-world替换为以下代码):
var a = 1;
function useForceUpdate() {
const [state, setState] = React.useState(true);
return [() => setState(!state)];
}
function App() {
const [forceUpdate] = useForceUpdate();
a++;
console.log(a);
return (
<div onClick={forceUpdate}>
{a}
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
在 codesandbox 上(只需将其中的 .js 文件替换为下面提供的文件:https://codesandbox.io/s/new?file=/src/App.js)它再次以值 3 开始,每次递增 2:
import React from "react";
var a = 1;
function useForceUpdate() {
const [state, setState] = React.useState(true);
return [() => setState(!state)]
}
function App() {
const [forceUpdate] = useForceUpdate();
a++;
console.log(a);
return (
<div onClick={forceUpdate}>
{a}
</div>
);
}
export default App;
为什么他们的行为如此不同?
发生这种情况是因为 React's Strict Mode
。React 的严格模式会双重调用某些函数,以识别您的应用程序中任何不需要的副作用。您可以在这里阅读更多相关信息:React Strict Mode
现在,如果您转到应用程序的 index.js
文件,您会看到该应用程序已被严格模式包装。 codesandbox 中 index.js 文件的情况类似。
例如,
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
rootElement
);
但是在 codepen 的情况下,代码没有任何 StrictMode 包装因此,它只添加一次到 a.
这是关于将文件分成模块,但我无法解释幕后到底发生了什么。最有可能的是,以某种方式连接模块只是读取文件,而不是将其代码包含在主代码中。这将增加变量。
您可以轻松查看:
- 第一种情况 - 在单独的文件(模块)中创建组件并将其导入根目录 index.js
- 第二种情况 - 在一个文件(模块)中通过调用 ReactDOM.render 创建组件
并在组件外添加console.log
- 在第一种情况下 - 您将看到 3 个日志,2 个位于组件外部,1 个位于组件内部。
- 第二种情况 - 2 根原木,1 根在外面,1 根在里面
当然在第一种情况下它以 3 开头,因为您使用的是捆绑代码。
但在我看来,在组件代码或状态管理器之外定义组件更改变量是错误的