[英]How to declare a global variable in React?
我在一個組件(應用程序中加載的第一個組件)中初始化了i18n
translation object 一次。 所有其他組件都需要相同的 object。 我不想在每個組件中重新初始化它。 有什么辦法? 使它對 window scope 可用並沒有幫助,因為我需要在render()
方法中使用它。
請為這些問題提出一個通用的解決方案,而不是 i18n 特定的解決方案。
您可能不知道導入已經是全局的。 如果導出對象(單例),則它可以作為導入語句全局訪問,也可以全局修改。
如果你想全局初始化一些東西但確保它只修改一次,你可以使用這種最初具有可修改屬性的單例方法,但是你可以在第一次使用后使用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/react-typescript-playground-forked-h8rpu
(我實際上在尋找什么)在這種情況下,您還可以在引用環境變量時干凈地初始化全局對象。
在項目的根目錄中創建一個帶有前綴REACT_APP_
變量的.env文件非常好。 您可以根據需要在 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
為什么不嘗試使用Context ?
您可以在任何父組件中聲明一個全局上下文變量,並且可以通過this.context.varname
跨組件樹訪問該變量。 您只需要在父組件中指定childContextTypes
和getChildContext
,然后您可以通過在子組件中指定contextTypes
從任何組件使用/修改它。
但是,請注意文檔中提到的這一點:
正如在編寫清晰的代碼時最好避免使用全局變量一樣,在大多數情況下您應該避免使用上下文。 特別是,在使用它來“保存輸入”並使用它而不是傳遞顯式道具之前,請三思。
不推薦但是....您可以使用您的應用程序類中的 componentWillMount 通過它添加全局變量...有點像這樣:
componentWillMount: function () {
window.MyVars = {
ajax: require('../helpers/ajax.jsx'),
utils: require('../helpers/utils.jsx')
};
}
仍然認為這是一個黑客......但它會完成你的工作
順便說一句, componentWillMount 在渲染前執行一次,在此處查看更多信息: https : //reactjs.org/docs/react-component.html#mounting-componentwillmount
在 ./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
可以在 webpack 中保留全局變量,即webpack.config.js
externals: {
'config': JSON.stringify(GLOBAL_VARIABLE: "global var value")
}
在 js 模塊中可以這樣讀
var config = require('config')
var GLOBAL_VARIABLE = config.GLOBAL_VARIABLE
希望這會有所幫助。
這是一種現代方法,使用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);
App.tsx(我們的主要入口點文件)
import './appGlobals'
// other code
anyWhereElseInTheApp.tsx
const chatGroupQuery = useQuery(GET_CHAT_GROUP_WITH_MESSAGES_BY_ID, {
variables: {
chatGroupId,
currentUserId: me.id,
messageLimit: globalThis.app.messageLimit, // 👈 used here.
},
});
到目前為止,我發現的最好方法是使用React Context,但將其隔離在高階提供者組件中。
您可以在 react https://facebook.github.io/react/docs/reusable-components.html#mixins 中使用 mixins 。
GlobalThis 可能在某些瀏覽器中受支持。
您可以參考以下鏈接
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.
這個答案是針對問題的global
部分而不是I18N
。
我想要一個global variable
和function
跨越我的應用程序的所有組件並且沒有父子關系。
This Answer
就像一個好答案; 但我還不是很清楚,所以我不得不按照自己的方式進行測試。
我使用了以下方法; 不確定這是“好的還是壞的做法” ,甚至是“題外話” ; 但分享以防萬一幫助某人。
Global.jsx
const Global = () => { }
export default Global;
Global.var = 100;
Global.func = () => {
Global.var += 1;
alert(Global.var);
}
MyComponent1.jsx
import Global from "./Global";
import React from "react";
const MyComponent1 = () => {
return ( <h1 onClick={Global.func}>COM1: {Global.var}</h1>)
}
export default MyComponent1;
MyComponent2.jsx
import Global from "./Global";
import React from "react";
const MyComponent2 = () => {
return ( <h1 onClick={Global.func}>COM2: {Global.var}</h1>)
}
export default MyComponent2;
像index.js
這樣的任何地方
root.render(
<div>
.
.
.
<MyComponent1/>
<MyComponent1/>
<MyComponent2/>
<MyComponent2/>
.
.
.
</div>
);
注意:這樣您就可以訪問全局function
或variable
; 但提供的示例無法更新(渲染)屏幕本身,因為沒有state
或prop
已更改。
我們可以像這樣更改解決方案,並像這樣在我們的Global Zone
中保留我們的組件或 DOM 對象的ref
(並不是說我不知道這是一個好的做法,甚至是最壞的情況;所以這取決於你自己) :
Global.jsx
const Global = () => { }
export default Global;
Global.var = 100;
Global.refs = [];
Global.inc = () => {
Global.var += 1;
Global.refs.forEach(ref => {
ref.current.innerText = Global.var;
});
}
MyComponent1.jsx
, MyComponent2.jsx
, ...
import Global from "./Global";
import React, { createRef } from "react";
const MyComponent1 = () => {
const ref = createRef();
Global.refs.push(ref);
return (<div onClick={Global.inc}>
<h2>COM1:</h2>
<h3 ref={ref} >{Global.var}</h3>
</div>);
};
export default MyComponent1;
我不知道他們想用“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
。
跨頁面/組件攜帶值的額外腳手架方法
您可以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
將此作為yourForm.jsx
保存到名為stores
的文件夾中。
然后您可以在另一個頁面中執行此操作:
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
中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.