简体   繁体   English

使用 create-react-app 创建的 React 应用程序无故增加模块范围的变量

[英]React application created using create-react-app increments module-scoped variable without reason

I have a React application created using create-react-app.我有一个使用 create-react-app 创建的 React 应用程序。 I was testing something and created the following piece of code:我正在测试一些东西并创建了以下代码:

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;

For some reason, it starts with a value of 3 and on every click it increments by 2 or 3 instead of 1, but that only happened on my already existing project which has additional libraries such as enzyme, react-hooks-testing-library and others.出于某种原因,它的值从 3 开始,每次点击它都会增加 2 或 3 而不是 1,但这仅发生在我已经存在的项目中,该项目具有额外的库,例如酶、react-hooks-testing-library 和其他。 On a new project where only the App.js code was changed, it starts with 3 and always increments by exactly 2 on clicking.在仅更改 App.js 代码的新项目中,它从 3 开始,并且在单击时始终以 2 为增量递增。 I tried it on codepen and there it starts with a value of 2 and increments by 1 as it should.我在 codepen 上尝试过它,它以 2 的值开始,并按应有的方式递增 1。 Here is the codepen (replace the.js file here: https://reactjs.org/redirect-to-codepen/hello-world with the following code):这是codepen(用以下代码替换.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')
);

And on codesandbox (just replace the.js file in this with the provided one below: https://codesandbox.io/s/new?file=/src/App.js ) it again starts with a value of 3 and increments by 2 every time:在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;

Why do they all behave so differently?为什么他们的行为如此不同?

This is happening because of React's Strict Mode .React's Strict Mode double invokes certain function in order to identify any unwanted side-effects in your app.发生这种情况是因为React's Strict Mode 。React 的严格模式双重调用某些 function 以识别您的应用程序中任何不需要的副作用。 You can read more about it here: React Strict Mode你可以在这里阅读更多信息: React Strict Mode

Now, if you go to the index.js file of your app you will see that the App is wrapped by Strict Mode.现在,如果你 go 到你的应用程序的index.js文件,你会看到应用程序被严格模式包装。 Similar is the case of index.js file in codesandbox. Codesandbox 中 index.js 文件的情况类似。

eg,例如,

const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <App />
  </StrictMode>,
  rootElement
);

However in case of codepen, the code dosen't have any StrictMode wrapping hence, it adds only once to a.但是,在 codepen 的情况下,代码没有任何 StrictMode 包装,因此,它只添加一次到 a.

It's about dividing files into modules, but I can't explain what exactly is happening under the hood.这是关于将文件划分为模块,但我无法解释引擎盖下到底发生了什么。 Most likely, connecting the module somehow just reads the file, rather than including its code in the main code.最有可能的是,以某种方式连接模块只是读取文件,而不是将其代码包含在主代码中。 This will increment the variable.这将增加变量。

You can easily check it:您可以轻松检查它:

  • First case - create component in separate file(module) and import it to root index.js第一种情况 - 在单独的文件(模块)中创建组件并将其导入到根 index.js
  • Second case - create component with call ReactDOM.render in one file (module)第二种情况 - 在一个文件(模块)中调用 ReactDOM.render 创建组件

And add console.log outside a component并在组件外添加 console.log

  • In first case - you will see 3 logs, 2 outside a component and one inside.在第一种情况下 - 您将看到 3 个日志,2 个在组件外部,一个在内部。
  • In second case - 2 logs, 1 outside and 1 inside在第二种情况下 - 2 个原木,1 个外部和 1 个内部

And of course it starts with 3 in first case because you work with bundled code.当然,在第一种情况下它以 3 开头,因为您使用的是捆绑代码。

But it seems to me that this is wrong to define component-changing variables outside the component code or state manager但在我看来,在组件代码或 state 管理器之外定义组件更改变量是错误的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在使用 create-react-app 创建的 reactjs 应用程序中导入 node_module dist js 文件 - Import a node_module dist js file in reactjs application created using create-react-app 将使用 create-react-app 创建的 React 应用程序集成到外部应用程序中 - Integrate React app created with create-react-app into an external application 如何从链接中删除“使用 create-react-app 创建”? - How to delete "created using create-react-app" from links? 使用create-react-app时如何在没有webpack依赖的情况下导入节点模块或JavaScript文件? - How to import node module or JavaScript file without webpack dependency when using create-react-app? 带有 create-react-app 的多模块项目 - Multi module projects with create-react-app 你如何在 Jest 中模拟一个模块范围的变量? - How do you mock a module-scoped variable in Jest? 使用 create-react-app 创建库 - Using create-react-app to create a library 如何在create-react-app创建的应用程序中使用jsx文件(不运行“npm run eject”)? - How to use jsx files in an app created by create-react-app (without run “npm run eject”)? 无法使用 create-react-app 创建新的 React 应用程序 - Cannot create a new React application with create-react-app 如何为使用 create-react-app 创建的 react 项目更新 webpack 配置? - How to update webpack config for a react project created using create-react-app?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM