如何在React中声明一个全局变量?

sap*_*apy 81 javascript-globalize reactjs

i18n在组件中初始化了翻译对象(在应用程序中加载的第一个组件).所有其他组件都需要相同的对象.我不想在每个组件中重新初始化它.怎么回事?使它可用于窗口范围没有帮助,因为我需要在render()方法中使用它.

请为这些问题建议一个通用的解决方案,而不是i18n特定的解决方案.

Nai*_*han 36

你为什么不尝试使用Context

您可以在任何父组件中声明全局上下文变量,并且可以在组件树中访问此变量this.context.varname.您只需要指定childContextTypesgetChildContext在父组件中,然后只需contextTypes在子组件中指定,就可以从任何组件中使用/修改它.

但请注意文档中提到的这一点:

正如在编写清晰代码时最好避免使用全局变量一样,在大多数情况下应避免使用上下文.特别是在使用它来"保存打字"并使用它而不是传递显式道具之前要三思而后行.

  • 关 .但是所有组件都没有父子关系,并且Context不能在该树之外工作.我想在整个应用程序中使用i18n. (24认同)
  • 可怕的答案. (6认同)
  • @sapy这就是为什么你应该使用 i18n 作为 redux 状态而不是作为上下文变量,请参阅我的答案:http://stackoverflow.com/questions/33413880/react-redux-and-multilingual-internationalization-apps-architecture/43733280# 43733280 (2认同)
  • 警告:这样的答案可能会触发 redux 专家。 (2认同)

小智 31

不推荐但....你可以使用app类中的componentWillMount来添加你的全局变量......有点像这样:

componentWillMount: function () {
    window.MyVars = {
        ajax: require('../helpers/ajax.jsx'),
        utils: require('../helpers/utils.jsx')
    };
}
Run Code Online (Sandbox Code Playgroud)

仍然认为这是一个黑客...但它将完成你的工作

btw componentWillMount在渲染之前执行一次,请在此处查看更多内容:https: //reactjs.org/docs/react-component.html#mounting-componentwillmount

  • 另请注意,`componentWillMount` 已被弃用:https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html (2认同)

Ali*_*eza 21

在 ./src 文件夹中创建一个名为“config.js”的文件,内容如下:

module.exports = global.config = {
    i18n: {
        welcome: {
            en: "Welcome",
            fa: "??? ?????"
        }
        // rest of your translation object
    }
    // other global config variables you wish
};
Run Code Online (Sandbox Code Playgroud)

在你的主文件“index.js”中加入这一行:

import './config';
Run Code Online (Sandbox Code Playgroud)

在任何需要对象的地方都使用这个:

global.config.i18n.welcome.en
Run Code Online (Sandbox Code Playgroud)


Jas*_*ing 14

超越React

您可能不知道导入已经是全局的。如果导出对象(单个),则可以将其作为导入语句全局访问,也可以全局修改

如果要全局初始化某事物,但确保仅对其进行一次修改,则可以使用这种最初具有可修改属性的单例方法,但是Object.freeze在首次使用后可以使用它来确保其在初始方案中不可变

const myInitObject = {}
export default myInitObject
Run Code Online (Sandbox Code Playgroud)

然后在您的init方法中引用它:

import myInitObject from './myInitObject'
myInitObject.someProp = 'i am about to get cold'
Object.freeze(myInitObject)
Run Code Online (Sandbox Code Playgroud)

由于myInitObject仍可以是全局引用,因此可以在任何地方引用该引用作为导入,但是如果有人尝试对其进行修改,它将保持冻结并抛出。

如果使用react-create-app

(实际上我在找什么)在这种情况下,您还可以在引用环境变量时干净地初始化全局对象。

在项目的根目录中创建一个带有前缀变量的.env文件,效果REACT_APP_很好。您可以process.env.REACT_APP_SOME_VAR根据需要在JS和JSX中进行引用,并且它在设计上是不可变的。

这样避免了必须window.myVar = %REACT_APP_MY_VAR%在HTML 中进行设置。

直接从Facebook查看有关此内容的更多有用信息:

https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables

  • 老实说,这是一个很好的提示,因为使用服务器端渲染,所以我的身份验证令牌遇到了麻烦。我最终在第一次加载时从localstorage加载,然后将其存储到我可以导入的单独的Config文件中。好答案。 (4认同)
  • 这是迄今为止最好的答案! (4认同)

Gol*_*Jer 7

这是globalThis我们在React Native应用程序中采用的现代方法。

globalThis 现在包含在...


appGlobals.ts

// define our parent property accessible via globalThis. Also apply the TypeScript type.
var app: globalAppVariables;

// define the child properties and their types. 
type globalAppVariables = {
  messageLimit: number;
  // more can go here. 
};

// set the values.
globalThis.app = {
  messageLimit: 10,
  // more can go here.
};


// Freeze so these can only be defined in this file.
Object.freeze(globalThis.app);
Run Code Online (Sandbox Code Playgroud)


App.tsx(我们的主要入口点文件

import './appGlobals'

// other code
Run Code Online (Sandbox Code Playgroud)


anyWhereElseInTheApp.tsx

const chatGroupQuery = useQuery(GET_CHAT_GROUP_WITH_MESSAGES_BY_ID, {
  variables: {
    chatGroupId,
    currentUserId: me.id,
    messageLimit: globalThis.app.messageLimit, //  used here.
  },
});
Run Code Online (Sandbox Code Playgroud)


小智 6

可以在 webpack ie 中保留全局变量 webpack.config.js

externals: {
  'config': JSON.stringify(GLOBAL_VARIABLE: "global var value")
}
Run Code Online (Sandbox Code Playgroud)

在 js 模块中可以这样读

var config = require('config')
var GLOBAL_VARIABLE = config.GLOBAL_VARIABLE
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助。


小智 6

创建一个文件:

import React from "react";

const AppContext = {};

export default AppContext;
    
Run Code Online (Sandbox Code Playgroud)

然后在 App.js 中更新值

import AppContext from './AppContext';
    
AppContext.username = uname.value;
    
Run Code Online (Sandbox Code Playgroud)

现在,如果您希望在另一个屏幕中使用用户名:

import AppContext from './AppContext';
    
Run Code Online (Sandbox Code Playgroud)

AppContext.username用于访问它。

还找到了另一种方法:设置值:localStorage.setItem('username', uname.value); 并获取值:localStorage.getItem("username");


Nic*_*dis 5

到目前为止,我发现的最好方法是使用React Context,但将其隔离在高阶提供者组件中