簡體   English   中英

如何在 React 中聲明一個全局變量?

[英]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-create-app

(我實際上在尋找什么)在這種情況下,您還可以在引用環境變量時干凈地初始化全局對象。

在項目的根目錄中創建一個帶有前綴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跨組件樹訪問該變量。 您只需要在父組件中指定childContextTypesgetChildContext ,然后您可以通過在子組件中指定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,但將其隔離在高階提供者組件中

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.

使用自定義掛鈎

如果您使用自定義掛鈎,則非常簡單

請參閱此鏈接https://stackoverflow.com/a/73678597/19969598

上面的帖子中提供了完整的示例用法

這個答案是針對問題的global部分而不是I18N

我想要一個global variablefunction跨越我的應用程序的所有組件並且沒有父子關系

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

注意:這樣您就可以訪問全局functionvariable 但提供的示例無法更新(渲染)屏幕本身,因為沒有stateprop已更改。

我們可以像這樣更改解決方案,並像這樣在我們的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM