如何在 React 中声明一个全局变量?
How to declare a global variable in React?
我在一个组件(应用程序中加载的第一个组件)中初始化了一次 i18n
翻译对象。在所有其他组件中都需要相同的对象。我不想在每个组件中重新初始化它。有什么办法?使其对 window 作用域可用没有帮助,因为我需要在 render()
方法中使用它。
请为这些问题提出一个通用的解决方案,而不是 i18n 特定的解决方案。
为什么不尝试使用 Context?
您可以在任何父组件中声明一个全局上下文变量,并且此变量将可以通过 this.context.varname
在整个组件树中访问。您只需在父组件中指定 childContextTypes
和 getChildContext
,然后您可以通过在子组件中指定 contextTypes
从任何组件 use/modify 这。
但是,请注意文档中提到的这一点:
Just as global variables are best avoided when writing clear code, you should avoid using context in most cases. In particular, think twice before using it to "save typing" and using it instead of passing explicit props.
不推荐,但是....您可以使用应用中的 componentWillMount class 通过它添加您的全局变量...有点像这样:
componentWillMount: function () {
window.MyVars = {
ajax: require('../helpers/ajax.jsx'),
utils: require('../helpers/utils.jsx')
};
}
仍然认为这是一个 hack...但它会完成你的工作
btw componentWillMount 在渲染之前执行一次,在这里查看更多信息:
https://reactjs.org/docs/react-component.html#mounting-componentwillmount
到目前为止我发现的最好方法是使用 React Context but to isolate it inside a high order provider component。
我不知道他们想用这个“React Context”的东西说什么 - 他们对我说希腊语,但我是这样做的:
函数之间的携带值,在同一页上
在您的构造函数中,绑定您的 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
.
额外的脚手架方法来承载价值pages/components
您可以将模型分配给 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
希望这会有所帮助。
超越 React
您可能没有意识到导入已经是全局的。如果导出一个对象(单例),那么它可以作为导入语句全局访问并且它也可以全局修改。
如果你想全局初始化一些东西但确保它只被修改一次,你可以使用这种 单例方法,它最初具有可修改的属性,但随后你可以使用 Object.freeze
在首次使用后确保它在您的初始场景中 不可变。
const myInitObject = {}
export default myInitObject
然后在你的初始化方法中引用它:
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)
如果使用 react-create-app
(我实际上是在寻找什么)在这种情况下,您还可以在引用环境变量时干净地初始化全局对象。
在项目的根目录下创建一个 .env 文件,其中包含前缀为 REACT_APP_
的变量,效果非常好。您可以根据需要在 JS 和 JSX process.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
,我们采用了我们的 React Native 应用程序。
globalThis
现在包含在...
- 现代浏览器 - MDN documentation
- 打字稿 3.4 - Handbook documentation
- ESLint v7 - Release notes
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
任何其他地方App.tsx
const chatGroupQuery = useQuery(GET_CHAT_GROUP_WITH_MESSAGES_BY_ID, {
variables: {
chatGroupId,
currentUserId: me.id,
messageLimit: globalThis.app.messageLimit, // used here.
},
});
全球某些浏览器可能支持此功能。
您可以参考以下链接
https://webpack.js.org/plugins/provide-plugin/
https://webpack.js.org/plugins/define-plugin/
也许它正在使用大锤来敲开坚果,但使用环境变量(使用 Dotenv https://www.npmjs.com/package/dotenv)您还可以在整个 React 应用程序中提供值。而且在使用它们的地方没有任何开销代码。
我来这里是因为我发现我的 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.
我在一个组件(应用程序中加载的第一个组件)中初始化了一次 i18n
翻译对象。在所有其他组件中都需要相同的对象。我不想在每个组件中重新初始化它。有什么办法?使其对 window 作用域可用没有帮助,因为我需要在 render()
方法中使用它。
请为这些问题提出一个通用的解决方案,而不是 i18n 特定的解决方案。
为什么不尝试使用 Context?
您可以在任何父组件中声明一个全局上下文变量,并且此变量将可以通过 this.context.varname
在整个组件树中访问。您只需在父组件中指定 childContextTypes
和 getChildContext
,然后您可以通过在子组件中指定 contextTypes
从任何组件 use/modify 这。
但是,请注意文档中提到的这一点:
Just as global variables are best avoided when writing clear code, you should avoid using context in most cases. In particular, think twice before using it to "save typing" and using it instead of passing explicit props.
不推荐,但是....您可以使用应用中的 componentWillMount class 通过它添加您的全局变量...有点像这样:
componentWillMount: function () {
window.MyVars = {
ajax: require('../helpers/ajax.jsx'),
utils: require('../helpers/utils.jsx')
};
}
仍然认为这是一个 hack...但它会完成你的工作
btw componentWillMount 在渲染之前执行一次,在这里查看更多信息: https://reactjs.org/docs/react-component.html#mounting-componentwillmount
到目前为止我发现的最好方法是使用 React Context but to isolate it inside a high order provider component。
我不知道他们想用这个“React Context”的东西说什么 - 他们对我说希腊语,但我是这样做的:
函数之间的携带值,在同一页上
在您的构造函数中,绑定您的 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
.
额外的脚手架方法来承载价值pages/components
您可以将模型分配给 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
希望这会有所帮助。
超越 React
您可能没有意识到导入已经是全局的。如果导出一个对象(单例),那么它可以作为导入语句全局访问并且它也可以全局修改。
如果你想全局初始化一些东西但确保它只被修改一次,你可以使用这种 单例方法,它最初具有可修改的属性,但随后你可以使用 Object.freeze
在首次使用后确保它在您的初始场景中 不可变。
const myInitObject = {}
export default myInitObject
然后在你的初始化方法中引用它:
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)
如果使用 react-create-app
(我实际上是在寻找什么)在这种情况下,您还可以在引用环境变量时干净地初始化全局对象。
在项目的根目录下创建一个 .env 文件,其中包含前缀为 REACT_APP_
的变量,效果非常好。您可以根据需要在 JS 和 JSX process.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
,我们采用了我们的 React Native 应用程序。
globalThis
现在包含在...
- 现代浏览器 - MDN documentation
- 打字稿 3.4 - Handbook documentation
- ESLint v7 - Release notes
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
任何其他地方App.tsx
const chatGroupQuery = useQuery(GET_CHAT_GROUP_WITH_MESSAGES_BY_ID, {
variables: {
chatGroupId,
currentUserId: me.id,
messageLimit: globalThis.app.messageLimit, // used here.
},
});
全球某些浏览器可能支持此功能。
您可以参考以下链接
https://webpack.js.org/plugins/provide-plugin/
https://webpack.js.org/plugins/define-plugin/
也许它正在使用大锤来敲开坚果,但使用环境变量(使用 Dotenv https://www.npmjs.com/package/dotenv)您还可以在整个 React 应用程序中提供值。而且在使用它们的地方没有任何开销代码。
我来这里是因为我发现我的 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.