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

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

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

506773 次浏览

你为什么不试试用 背景呢?

您可以在任何父组件中声明一个全局上下文变量,这个变量可以通过 this.context.varname在整个组件树中访问。您只需要在父组件中指定 childContextTypesgetChildContext,然后您可以通过在子组件中指定 contextTypes在任何组件中使用/修改它。

然而,请注意文件中提到的这一点:

正如在编写清晰代码时最好避免使用全局变量一样,在大多数情况下应该避免使用上下文。特别是,在使用它“保存输入”并使用它而不是传递显式道具之前,请三思。

不推荐,但是..。你可以从你的应用程序类中使用 Component entWillMount 添加你的全局变量,有点像这样:

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

仍然认为这是黑客行为... 但它会让你的工作完成

Btw Component WillMount 在呈现之前执行一次,请参阅这里的更多信息: Https://reactjs.org/docs/react-component.html#mounting-componentwillmount

到目前为止,我发现的最好的方法是使用 反应环境,但是将它隔离在 高阶提供者组件中。

我不知道他们想用“反应语境”这种东西说什么——他们对我说的是希腊语,但我是这样做的:

在同一页上在函数之间传递值

在构造函数中,绑定 setter:

this.setSomeVariable = this.setSomeVariable.bind(this);

然后在构造函数下面声明一个函数:

setSomeVariable(propertyTextToAdd) {
this.setState({
myProperty: propertyTextToAdd
});
}

当您想要设置它时,调用 this.setSomeVariable("some value");

(你甚至可以逃脱 this.state.myProperty = "some value";)

当你想得到它,呼叫 var myProp = this.state.myProperty;

使用 alert(myProp);应该给你 some value

额外的脚手架方法在页面/组件之间传输值

你可以指定一个模型到 this(技术上来说是 this.stores) ,这样你就可以用 this.state来引用它:

import Reflux from 'reflux'
import Actions from '~/actions/actions'


class YourForm extends Reflux.Store
{
constructor()
{
super();
this.state = {
someGlobalVariable: '',
};
this.listenables = Actions;
this.baseState = {
someGlobalVariable: '',
};
}


onUpdateFields(name, value) {
this.setState({
[name]: value,
});
}


onResetFields() {
this.setState({
someGlobalVariable: '',
});
}
}
const reqformdata = new YourForm


export default reqformdata

将其保存到名为 stores的文件夹中,作为 yourForm.jsx

然后你可以在另一个页面做到这一点:

import React from 'react'
import Reflux from 'reflux'
import {Form} from 'reactstrap'
import YourForm from '~/stores/yourForm.jsx'


Reflux.defineReact(React)


class SomePage extends Reflux.Component {
constructor(props) {
super(props);
this.state = {
someLocalVariable: '',
}
this.stores = [
YourForm,
]
}
render() {


const myVar = this.state.someGlobalVariable;
return (
<Form>
<div>{myVar}</div>
</Form>
)
}
}
export default SomePage

如果在另一个组件中使用如下函数设置 this.state.someGlobalVariable:

setSomeVariable(propertyTextToAdd) {
this.setState({
myGlobalVariable: propertyTextToAdd
});
}

在构造函数中绑定的:

this.setSomeVariable = this.setSomeVariable.bind(this);

使用上面显示的代码,propertyTextToAdd中的值将显示在 SomePage中。

可以在 webpack 中保存全局变量,例如在 webpack.config.js

externals: {
'config': JSON.stringify({ GLOBAL_VARIABLE: "global var value" })
}

在 js 模块中可以像

var config = require('config')
var GLOBAL_VARIABLE = config.GLOBAL_VARIABLE

希望这个能帮上忙。

超越反应

你可能没有意识到 进口已经是全球性的了。如果导出一个对象(单例) ,那么它可以作为 import 语句和 它也可以在全局范围内进行修改进行全局访问。

如果您希望在全局范围内初始化某个东西,但是确保它只被修改一次,那么您可以使用这个 单独进场,它最初具有可修改的属性,但是在它第一次使用之后,您可以使用 Object.freeze来确保它在您的初始场景中的 永恒不变

const myInitObject = {}
export default myInitObject

然后在 init 方法中引用它:

import myInitObject from './myInitObject'
myInitObject.someProp = 'i am about to get cold'
Object.freeze(myInitObject)

myInitObject仍然是全局的,因为它可以在任何地方引用 作为进口,但仍然会被冻结,如果有人试图修改它扔。

使用单例的反应状态示例

Https://codesandbox.io/s/adoring-architecture-ru3vt (见 UserContext.tsx)

如果使用 response-create-app

在这个场景中,当引用环境变量时,还可以清晰地初始化全局对象。

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

这样就避免了在 HTML 中设置 window.myVar = %REACT_APP_MY_VAR%

请直接从 Facebook 上查看更多有用的细节:

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

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

module.exports = global.config = {
i18n: {
welcome: {
en: "Welcome",
fa: "خوش آمدید"
}
// rest of your translation object
}
// other global config variables you wish
};

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

import './config';

在任何你需要你的物体的地方使用这个:

global.config.i18n.welcome.en

这里是一个现代的方法,使用 globalThis,我们采取了我们的 本土反应应用程序。

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);


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

import './appGlobals'


// other code


应用程序中的任何地方

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

也许它是使用一个大锤敲碎坚果,但使用环境变量(与 Dotenv https://www.npmjs.com/package/dotenv) ,您也可以提供整个反应应用程序的值。而且没有任何开销代码,他们使用的地方。

我来这里是因为我发现在我的 env 文件中定义的一些变量在不同的 env 文件中都是静态的,所以我寻找了一种方法将它们移出 env 文件。但说实话,我不喜欢我在这里找到的任何选择。我不想在每次需要这些值时都设置和使用上下文。

我对环境没有经验,所以如果这种方法有缺点,请让我知道。

只是为了宣告什么,试试这个。确保在适当的时候分配 MyObj,因为您想在 render()中访问它,在这个线程之前发布了许多方法。也许是 if undefined then create it完成这项工作最简单的方法之一。

declare global {
interface Window {
MyObj: any;
}
}
Create a file :


import React from "react";


const AppContext = {};


export default AppContext;


then in App.js, update the value
import AppContext from './AppContext';




AppContext.username = uname.value;


Now if you want the username to be used in another screen:


import AppContext from './AppContext';


AppContext.username to be used for accessing it.

使用定制钩子

如果您使用自定义钩子,那么它非常简单

请参考此链接 Https://stackoverflow.com/a/73678597/19969598

完整的样本使用情况可以在上面的文章中找到