Làm thế nào để khai báo một biến toàn cục trong React?


106

Tôi đã khởi tạo i18nđối tượng dịch một lần trong một thành phần (thành phần đầu tiên tải trong ứng dụng). Đối tượng tương tự được yêu cầu Trong tất cả các thành phần khác. Tôi không muốn khởi tạo lại nó trong mọi thành phần. Con đường xung quanh là gì? Làm cho nó có sẵn cho phạm vi cửa sổ không giúp ích gì vì tôi cần sử dụng nó trong render()phương thức.

Vui lòng đề xuất một giải pháp chung cho những vấn đề này và không phải giải pháp cụ thể cho i18n.


1
Bạn có thể sử dụng Reduxhoặc Fluxthư viện có thể xử lý dữ liệu hoặc trạng thái trên toàn cầu. và bạn có thể vượt qua nó một cách dễ dàng thông qua tất cả các thành phần của bạn
vistajess

Bất kỳ cách nào khác ? Chúng tôi bắt đầu dự án mà không có bất kỳ khung React nào vì nó là ngày đầu của React. Bây giờ kết nối mọi thành phần với Redux store sẽ đòi hỏi nỗ lực rất lớn.
sapy

3
Một cái gì đó giống như phản ứng toàn cầu làm việc cho bạn?
TwoStraws

Câu trả lời:


50

Tại sao bạn không thử sử dụng Context ?

Bạn có thể khai báo một biến ngữ cảnh toàn cục trong bất kỳ thành phần mẹ nào và biến này sẽ có thể truy cập được trên cây thành phần bằng this.context.varname. Bạn chỉ phải chỉ định childContextTypesgetChildContexttrong thành phần mẹ và sau đó bạn có thể sử dụng / sửa đổi điều này từ bất kỳ thành phần nào bằng cách chỉ định contextTypestrong thành phần con.

Tuy nhiên, hãy lưu ý điều này như đã đề cập trong tài liệu:

Cũng như các biến toàn cục tốt nhất nên tránh khi viết mã rõ ràng, bạn nên tránh sử dụng ngữ cảnh trong hầu hết các trường hợp. Đặc biệt, hãy suy nghĩ kỹ trước khi sử dụng nó để "tiết kiệm đánh máy" và sử dụng nó thay vì chuyển các đạo cụ rõ ràng.


30
đóng . nhưng Tất cả thành phần không có mối quan hệ con gốc và Ngữ cảnh không hoạt động ngoài cây đó. Tôi muốn i18n trên Ứng dụng.
sapy

@sapy, đây là lý do tại sao bạn nên sử dụng i18n làm trạng thái redux chứ không phải là một biến ngữ cảnh, hãy xem câu trả lời của tôi ở đây: stackoverflow.com/questions/33413880/…
Alnamrouti được bổ sung vào

9
Câu trả lời kinh khủng.
r3wt

Từ phía tôi, tôi khuyên bạn nên sử dụng redux thay thế và đặc biệt cho các Ứng dụng lớn
Hosny Ben

37

Ngoài React

Bạn có thể không biết rằng quá trình nhập đã có tính toàn cầu . Nếu bạn xuất một đối tượng (singleton) thì nó có thể truy cập toàn cầu dưới dạng câu lệnh nhập và nó cũng có thể được sửa đổi trên toàn cầu .

Nếu bạn muốn khởi tạo thứ gì đó trên toàn cầu nhưng đảm bảo nó chỉ được sửa đổi một lần, bạn có thể sử dụng phương pháp singleton này ban đầu có các thuộc tính có thể sửa đổi nhưng sau đó bạn có thể sử dụng Object.freezesau lần sử dụng đầu tiên để đảm bảo nó không thay đổi trong kịch bản init của bạn.

const myInitObject = {}
export default myInitObject

sau đó trong phương thức init của bạn tham chiếu nó:

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

Các myInitObjectvẫn sẽ là toàn cầu vì nó có thể được tham chiếu bất cứ nơi nào như một nhập khẩu nhưng sẽ vẫn đông lạnh và ném nếu cố gắng bất cứ ai để sửa đổi nó.

Nếu sử dụng react-create-app

(những gì tôi đang tìm kiếm thực sự) Trong trường hợp này, bạn cũng có thể khởi tạo các đối tượng toàn cục một cách sạch sẽ khi tham chiếu đến các biến môi trường.

Tạo một tệp .env ở gốc của dự án của bạn với REACT_APP_các biến có tiền tố bên trong khá hay. Bạn có thể tham chiếu trong JS và JSX của mình process.env.REACT_APP_SOME_VARkhi bạn cần VÀ nó bất biến theo thiết kế.

Điều này tránh phải đặt window.myVar = %REACT_APP_MY_VAR%trong HTML.

Xem thêm chi tiết hữu ích về điều này từ Facebook trực tiếp:

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


6
Đây thực sự là một mẹo hay, tôi đã gặp sự cố với mã thông báo xác thực của mình vì tôi đang sử dụng Kết xuất phía máy chủ. Tôi đã kết thúc tải từ localstorage trong lần tải đầu tiên và sau đó lưu trữ nó vào một tệp Cấu hình riêng biệt mà tôi có thể nhập. Câu trả lời chính xác.
8

1
Đây là câu trả lời tốt nhất cho đến nay!
thiloilg

33

Không được khuyến nghị nhưng .... bạn có thể sử dụng componentWillMount từ lớp ứng dụng của mình để thêm các biến toàn cục của mình ... hơi giống như vậy:

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

vẫn coi đây là một vụ hack ... nhưng nó sẽ hoàn thành công việc của bạn

btw componentWillMount thực thi một lần trước khi hiển thị, xem thêm tại đây: https://reactjs.org/docs/react-component.html#mounting-componentwillmount


1
Đó là một bản hack cho các trường hợp sử dụng nhất định. Tôi đang tích hợp một ứng dụng React vào bối cảnh của một ứng dụng không phải React khác tại công ty của tôi. Đây có vẻ như là một cách tuyệt vời để hiển thị các phương thức công khai cho ứng dụng đang sử dụng. Liệu tôi có sai? Có cách nào tốt hơn?
mccambridge

2
Cũng xin lưu ý rằng componentWillMountnó sẽ không được dùng nữa: reactjs.org/blog/2018/03/27/update-on-async-rendering.html
RyanNerd,

@mccambridge Tôi biết điều này là muộn nhưng tôi sẽ gửi một hàm từ ứng dụng không phải React vào React mà bạn sẽ gọi để gửi thông tin. Btw, bạn có thể làm điều này với iframe.
Nic Szerman,

6

Tạo một tệp có tên "config.js" trong thư mục ./src với nội dung sau:

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

Trong tệp chính của bạn "index.js", hãy đặt dòng này:

import './config';

Mọi nơi bạn cần đối tượng của mình, hãy sử dụng cái này:

global.config.i18n.welcome.en

5

Có thể giữ các biến toàn cục trong webpack tức là trong webpack.config.js

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

Trong mô-đun js có thể đọc như

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

Hy vọng điều này sẽ giúp ích.



2

Bạn có thể sử dụng mixin trong react https://facebook.github.io/react/docs/reusable-components.html#mixins .


7
Lưu ý: Nếu bạn đang sử dụng Cú pháp ES6 (hiện được khuyến khích sử dụng) hoặc các thành phần thuần túy, thì các mixin sẽ không khả dụng. Lời khuyên là hãy soạn các thành phần của bạn. medium.com/@dan_abramov/…
Aren

1
này có vẻ như là một ý tưởng tốt như sau đó bạn có thể tập trung logic của bạn và sau đó chuyển sang Flux loại dung lượng lưu trữ (ví dụ LocalStorage hoặc phía khách hàng DB)
dcsan

2
Câu trả lời này nên được mở rộng để bao gồm một mẫu mã. Các liên kết có thể bị phá vỡ.
vapcguy

0

Đây là một cách tiếp cận hiện đại globalThis, chúng tôi đã sử dụng cho ứng dụng React Native của mình .

globalThis hiện được đưa vào ...


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 ( tệp điểm nhập chính của chúng tôi )

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

Tôi không biết họ đang cố gắng nói gì với thứ "Bối cảnh phản ứng" này - họ đang nói tiếng Hy Lạp với tôi, nhưng đây là cách tôi đã làm điều đó:

Mang các giá trị giữa các chức năng, trên cùng một trang

Trong phương thức khởi tạo của bạn, hãy ràng buộc trình thiết lập của bạn:

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

Sau đó khai báo một hàm ngay bên dưới hàm tạo của bạn:

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

Khi bạn muốn đặt nó, hãy gọi this.setSomeVariable("some value");

(Bạn thậm chí có thể thoát khỏi this.state.myProperty = "some value"; )

Khi bạn muốn lấy nó, hãy gọi var myProp = this.state.myProperty;

Sử dụng alert(myProp);sẽ cung cấp cho bạn some value.

Phương pháp giàn giáo bổ sung để mang các giá trị trên các trang / thành phần

Bạn có thể gán một mô hình cho this(về mặt kỹ thuật this.stores), vì vậy bạn có thể tham chiếu nó với 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

Lưu nó vào một thư mục có tên storesyourForm.jsx.

Sau đó, bạn có thể làm điều này trong một trang khác:

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

Nếu bạn đã đặt this.state.someGlobalVariabletrong một thành phần khác bằng một hàm như:

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

mà bạn liên kết trong hàm tạo với:

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

giá trị trong propertyTextToAddsẽ được hiển thị SomePagebằng cách sử dụng mã hiển thị ở trên.


3
Xin lỗi vì tôi là người mới ở đây nhưng tôi chỉ mới học React và không chắc tại sao câu trả lời này lại nhận được rất nhiều
phiếu phản đối

3
@someoneuseless Chính xác! Và đó là lý do tại sao tôi từ chối xóa nó và quỳ lạy công chúng. Chỉ vì họ muốn sử dụng "Context" (bất cứ điều gì đó) và những đồ vật vui nhộn khác này không có nghĩa là mọi người đều cần. Đập tay!
vapcguy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.