Reactでグローバル変数を宣言する方法は?


106

i18n翻訳オブジェクトをコンポーネント(アプリに読み込まれる最初のコンポーネント)で1回初期化しました。他のすべてのコンポーネントでは、同じオブジェクトが必要です。すべてのコンポーネントで再初期化したくありません。どうすればいいの?render()メソッドで使用する必要があるため、ウィンドウスコープで使用できるようにしても効果がありません。

i18n固有のソリューションではなく、これらの問題の一般的なソリューションを提案してください。


1
あなたは使用することができReduxたりFlux、グローバルデータや状態を扱うことができるライブラリ。すべてのコンポーネントに簡単に渡すことができます
vistajess

その他の方法で ?React Frameworkを使用せずにプロジェクトを開始したのは、Reactの初日だったからです。すべてのコンポーネントをReduxストアに接続するには、多大な労力が必要になります。
2015

3
グローバル反応のようなものはあなたのために働きますか?
TwoStraws、2015

回答:


50

コンテキストを使用してみませんか?

親コンポーネントのいずれかでグローバルコンテキスト変数を宣言できます。この変数には、コンポーネントツリー全体でからアクセスできますthis.context.varname。あなただけ指定する必要がありますchildContextTypesし、getChildContext親コンポーネントで、その後、あなただけ指定することで、任意のコンポーネントからこれを修正する/使用することができるcontextTypes子コンポーネントに。

ただし、ドキュメントに記載されているように、この点に注意してください。

明確なコードを書くときにグローバル変数を回避するのが最善であるのと同様に、ほとんどの場合、コンテキストの使用を回避する必要があります。特に、「タイピングを保存する」ためにそれを使用し、明示的な小道具を渡す代わりにそれを使用する前に、よく考えてください。


30
閉じる。しかし、すべてのコンポーネントには親子関係がなく、コンテキストはそのツリーを超えて機能しません。アプリケーション全体でi18nが必要です。
2015

@sapyあなたがここに私の答えを見ていないコンテキスト変数としてReduxの状態として、国際化を使うべき理由です:stackoverflow.com/questions/33413880/...を
ファリードAlnamrouti

9
恐ろしい答え。
r3wt 2018

私の側からは、代わりにreduxを使用することをお勧めします。特に大きなアプリの場合
Hosny Ben

37

反応を超えて

インポートがすでにグローバルであることに気付かないかもしれません。オブジェクト(シングルトン)をエクスポートすると、インポートステートメントとしてグローバルにアクセスでき、グローバルに変更することもできます

何かをグローバルに初期化したいが、一度だけ変更されるようにする場合は、最初に変更可能なプロパティを持つこのシングルトンアプローチを使用できますがObject.freeze、最初の使用後に使用して、初期シナリオで不変であることを確認できます。

const myInitObject = {}
export default myInitObject

次に、それを参照するinitメソッドで:

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

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


6
これは正直言ってすばらしいヒントです。サーバー側レンダリングを使用しているため、認証トークンに問題がありました。最初のロードでlocalstorageからロードし、それをインポートできる別のConfigファイルに格納しました。すばらしい答えです。

1
これが今のところ最良の答えです!
thiloilg

33

推奨されませんが、...アプリクラスのcomponentWillMountを使用してグローバル変数を追加できます...

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

まだこれをハックと見なします...しかし、それはあなたの仕事を成し遂げるでしょう

btw componentWillMountはレンダリングの前に1回実行されます。詳細については、https//reactjs.org/docs/react-component.html#mounting-componentwillmountを参照して ください。


1
特定のユースケースのハックです。Reactアプリを会社の別の非Reactアプリのコンテキストに統合しています。これは、使用するアプリのパブリックメソッドを公開する優れた方法のようです。私が間違っている?もっと良い方法はありますか?
mccambridge

2
またcomponentWillMount、廃止予定であることにも注意してください:reactjs.org/blog/2018/03/27/update-on-async-rendering.html
RyanNerd '29

@mccambridge私はこれが遅いことを知っていますが、情報を送信するために呼び出す関数を、React以外のアプリからReactに送信します。ところで、iframeでこれを行うことができます。
Nic Szerman、2018

6

次の内容で、。/ 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

5

グローバル変数をWebpack内、つまり webpack.config.js

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

jsモジュールでは次のように読むことができます

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

これがお役に立てば幸いです。



2

7
注:ES6構文(現在は推奨)または純粋なコンポーネントを使用している場合、ミックスインは使用できません。お勧めは、コンポーネントを作成することです。medium.com/@dan_abramov/...
AREN

1
ロジックを一元化して、後でFluxの他のタイプのストレージ(Localstorageまたはクライアント側のDBなど)に移動できるため、これは良いアイデアのようです
dcsan

2
この回答は、コードサンプルを含めるように拡張されているはずです。リンクが壊れることがあります。
vapcguy

0

ここでは現代的なアプローチがあり、使用して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


anyWhereElseInTheApp.tsx

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

-6

彼らがこの "React Context"のことで何を言おうとしているのかわかりません。

同じページの関数間で値を運ぶ

コンストラクターで、セッターをバインドします。

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

フォルダにこれを保存しstoresyourForm.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ます。


3
申し訳ありませんが、ここで新しいものが、のために、私はちょうどこの答えは、そう多くはdownvotedを取得する理由がわからない反応し、学ぶ
someoneuseless

3
@someoneuselessまさに!そしてそれが私がそれを削除することを拒否し、大衆に追いつく理由です。彼らが「コンテキスト」(それが何であれ)を使用したいという理由だけで、これらの他の面白いオブジェクトは誰もが必要とすることを意味しません。ハイタッチ!
vapcguy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.