React'te global bir değişken nasıl tanımlanır?


117

i18nÇeviri nesnesini bir bileşende bir kez başlattım (uygulamada yüklenen ilk bileşen). Diğer tüm bileşenlerde aynı nesne gereklidir. Her bileşende yeniden başlatmak istemiyorum. Yol nedir? render()Yöntemde kullanmam gerektiğinden pencere kapsamı için kullanılabilir hale getirmek yardımcı olmuyor .

Lütfen bu sorunlar için i18n'ye özel bir çözüm değil, genel bir çözüm önerin.


1
Global olarak verileri veya durumu işleyebilen Reduxveya Fluxkitaplığı kullanabilirsiniz . ve onu tüm bileşenlerinizden kolayca geçirebilirsiniz
2015 vistajess

Başka bir yol var mı? Projeye herhangi bir React Framework olmadan başladık çünkü React'in erken bir günüydü. Artık her bileşeni Redux mağazasına bağlamak büyük çaba gerektirecektir.
sapy

3
React-global çalışma gibi bir şey sizin için mi?
TwoStraws

Yanıtlar:


52

Neden Bağlam kullanmayı denemiyorsun ?

Üst bileşenlerin herhangi birinde global bir bağlam değişkeni tanımlayabilirsiniz ve bu değişkene tarafından bileşen ağacından erişilebilir this.context.varname. Yalnızca belirtmek zorunda childContextTypesve getChildContextebeveyn bileşeninde ve bundan sonra kullanmayı / sadece belirtilerek herhangi bileşenden bu değiştirebilir contextTypesçocuk bileşeninde.

Ancak, lütfen belgelerde belirtildiği gibi bunu not edin:

Net kod yazarken en iyi genel değişkenlerden kaçınıldığı gibi, çoğu durumda bağlam kullanmaktan kaçınmalısınız. Özellikle, "yazmayı kaydetmek" için kullanmadan ve açık sahne aktarımı yerine onu kullanmadan önce iki kez düşünün.


32
kapat . ancak Tüm bileşenin üst alt ilişkisi yoktur ve Bağlam bu ağacın ötesinde çalışmaz. Uygulama genelinde i18n istiyorum.
sapy

@sapy bu yüzden i18n'i bir bağlam değişkeni olarak değil, redux durumu olarak kullanmalısınız cevabımı burada görebilirsiniz: stackoverflow.com/questions/33413880/…
Fareed Alnamrouti

10
Korkunç cevap.
r3wt

Benim açımdan bunun yerine redux kullanmanızı tavsiye ederim ve özellikle büyük Uygulamalar için
Hosny Ben

41

React'in Ötesinde

Bir içe aktarmanın zaten global olduğunun farkında olmayabilirsiniz . Bir nesneyi (tekli) dışa aktarırsanız, o zaman global olarak bir ithalat ifadesi olarak erişilebilir hale gelir ve aynı zamanda genel olarak da değiştirilebilir .

Bir şeyi global olarak başlatmak, ancak yalnızca bir kez değiştirilmesini sağlamak istiyorsanız, başlangıçta değiştirilebilir özelliklere sahip olan bu tekli yaklaşımı kullanabilirsiniz , ancak daha Object.freezesonra ilk kullanımdan sonra, başlangıç ​​senaryonuzda değişmez olmasını sağlamak için kullanabilirsiniz .

const myInitObject = {}
export default myInitObject

sonra onu referans veren init yönteminizde:

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

myInitObjectHer yerde başvurulabilir hala küresel olacak bir ithalat olarak ama donmuş kalır ve kimse girişimleri değiştirmek için eğer atar.

React-create-app kullanıyorsanız

(aslında aradığım şey) Bu senaryoda, ortam değişkenlerine atıfta bulunurken genel nesneleri temiz bir şekilde başlatabilirsiniz.

Projenizin kök dizininde, önekli REACT_APP_değişkenler içeren bir .env dosyası oluşturmak oldukça güzel. JS ve JSX'inizde process.env.REACT_APP_SOME_VARihtiyaç duyduğunuzda referans verebilirsiniz VE tasarım gereği değiştirilemez.

Bu window.myVar = %REACT_APP_MY_VAR%, HTML'de ayarlama zorunluluğunu ortadan kaldırır .

Bununla ilgili daha yararlı ayrıntıları doğrudan Facebook'tan görün:

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


7
Bu gerçekten harika bir ipucu, Sunucu Tarafı Oluşturmayı kullandığım için kimlik doğrulama belirteçlerimle ilgili sorun yaşıyordum. İlk yüklemede yerel depodan yükleme yaptım ve ardından bunu içe aktarabileceğim ayrı bir Yapılandırma dosyasına depoladım. Mükemmel cevap.
Sekiz

2
Şimdiye kadarki en iyi cevap bu!
thiloilg

1
Dostum, bu gözlerimi olması gerekenden çok daha fazla açtı ... Teşekkür ederim, bundan sonra% 20 daha iyi olacağımı düşünüyorum FE geliştirici: P
Outside_Box

34

Önerilmez, ancak .... uygulama sınıfınızdan componentWillMount'u kullanarak global değişkenlerinizi ekleyebilirsiniz ... bunun gibi biraz:

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

Yine de bunu bir hack olarak düşünün ... ama işinizi halledecektir

btw componentWillMount, oluşturmadan önce bir kez çalıştırılır, daha fazlasını burada görebilirsiniz: https://reactjs.org/docs/react-component.html#mounting-componentwillmount


1
Belirli kullanım durumları için bir hack. Şirketimde bir React uygulamasını başka bir React dışı uygulamanın bağlamına entegre ediyorum. Bu, tüketen uygulama için herkese açık yöntemleri ortaya çıkarmanın harika bir yolu gibi görünüyor. Yanlış mıyım? Daha iyi bir yol var mı?
mccambridge

2
Ayrıca bunun componentWillMountkullanımdan kaldırıldığını unutmayın: reactjs.org/blog/2018/03/27/update-on-async-rendering.html
RyanNerd

@mccambridge Bunun geç olduğunu biliyorum, ancak React dışı uygulamadan React'e bilgi göndermek için arayacağınız bir işlev gönderirim. Btw, bunu iframe'lerle yapabilirsiniz.
Nic Szerman

9

Bu içerikle ./src klasöründe "config.js" adlı bir dosya oluşturun:

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

Ana dosyanıza "index.js" şu satırı koyun:

import './config';

Nesnenize ihtiyacınız olan her yerde şunu kullanın:

global.config.i18n.welcome.en

5

Global değişkenleri web paketinde tutabilir, yani webpack.config.js

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

Js modülünde gibi okuyabilir

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

Umarım bu yardımcı olur.



2

7
Not: ES6 Sözdizimi (şimdi tavsiye edilmektedir) veya saf bileşenler kullanıyorsanız, karışımlar mevcut değildir. Tavsiye, bileşenlerinizi oluşturmaktır. medium.com/@dan_abramov/…
Aren

1
mantığınızı merkezileştirip daha sonra Flux'a diğer depolama türlerine (örn. Yerel depolama veya istemci tarafı DB)
geçebileceğiniz için

2
Bu yanıt, bir kod örneği içerecek şekilde genişletilmeliydi. Bağlantılar kopabilir.
vapcguy


1

İşte React Native uygulamamız globalThisiçin kullandığımız modern bir yaklaşım .

globalThis şimdi dahil ...


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 ( ana giriş noktası dosyamız )

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

Bu "React Context" şeyiyle ne söylemeye çalıştıklarını bilmiyorum - benim için Yunanca konuşuyorlar, ama ben bunu şöyle yaptım:

Değerleri fonksiyonlar arasında aynı sayfada taşımak

Yapıcınızda ayarlayıcınızı bağlayın:

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

Ardından kurucunuzun hemen altında bir işlev bildirin:

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

Ayarlamak istediğinizde arayın this.setSomeVariable("some value");

(Kurtulabilirsin bile this.state.myProperty = "some value";)

Almak istediğinde ara var myProp = this.state.myProperty;

Kullanmak alert(myProp);size vermelidir some value.

Sayfalar / bileşenler arasında değerleri taşımak için ekstra iskele yöntemi

Bir modeli this(teknik olarak this.stores) atayabilirsiniz , böylece daha sonra şununla referans alabilirsiniz 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

Adlı bir klasöre bu kaydet storesolarak yourForm.jsx.

Sonra bunu başka bir sayfada yapabilirsiniz:

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

Aşağıdaki this.state.someGlobalVariablegibi bir işlevi kullanarak başka bir bileşen ayarladıysanız :

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

yapıcıda şununla bağladığınız:

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

içindeki değer, yukarıda gösterilen kod kullanılarak propertyTextToAddgörüntülenecektir SomePage.


3
Burada yeni olduğum için üzgünüm ama sadece React'i öğrendim ve bu cevabın neden bu kadar çok olumsuz oy aldığından emin değilim
kimse kullanılmaz

3
@someoneuseless Kesinlikle! İşte bu yüzden onu silmeyi ve kitlelere yemin etmeyi reddediyorum. Sırf "Bağlam" (her neyse) kullanmak istedikleri için ve bu diğer komik nesneler herkesin buna ihtiyacı olduğu anlamına gelmez. Çak beşlik!
vapcguy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.