एक प्रतिक्रिया घटक के बाहर रेडक्स स्टोर तक पहुंचने का सबसे अच्छा तरीका क्या है?


191

@connectजब मैं एक प्रतिक्रिया घटक के भीतर स्टोर तक पहुँचने की कोशिश कर रहा हूँ तो बहुत अच्छा काम करता है। लेकिन मुझे इसे किसी अन्य बिट कोड में कैसे एक्सेस करना चाहिए। उदाहरण के लिए: मान लीजिए कि मैं अपने अक्षतंतु उदाहरण बनाने के लिए एक प्राधिकरण टोकन का उपयोग करना चाहता हूं जिसे मेरे ऐप में विश्व स्तर पर उपयोग किया जा सकता है, इसे प्राप्त करने का सबसे अच्छा तरीका क्या होगा?

यह मरा है api.js

// tooling modules
import axios from 'axios'

// configuration
const api = axios.create()
api.defaults.baseURL = 'http://localhost:5001/api/v1'
api.defaults.headers.common['Authorization'] = 'AUTH_TOKEN' // need the token here
api.defaults.headers.post['Content-Type'] = 'application/json'

export default api

अब मैं अपने स्टोर से एक डेटा बिंदु का उपयोग करना चाहता हूं, यहां वह है जो ऐसा लगेगा जैसे मैं उपयोग करने के बाद एक प्रतिक्रिया घटक के भीतर लाने की कोशिश कर रहा था @connect

// connect to store
@connect((store) => {
  return {
    auth: store.auth
  }
})
export default class App extends Component {
  componentWillMount() {
    // this is how I would get it in my react component
    console.log(this.props.auth.tokens.authorization_token) 
  }
  render() {...}
}

किसी भी अंतर्दृष्टि या कार्यप्रवाह पैटर्न वहाँ?


आप नहीं चाहते हैं कि आप Axux उदाहरण के लिए एक redux मिडलवेयर में रहें? यह आपके सभी आवेदन इस तरह से उपलब्ध होगा
Emrys Myrooin

आप कक्षा apiमें आयात कर सकते हैं Appऔर प्राधिकरण टोकन प्राप्त करने के बाद आप कर सकते हैं api.defaults.headers.common['Authorization'] = this.props.auth.tokens.authorization_token;, और साथ ही साथ आप इसे लोकलस्टोरेज में भी स्टोर कर सकते हैं, इसलिए जब उपयोगकर्ता पृष्ठ को रीफ्रेश करता है, तो आप जांच सकते हैं कि टोकन लोकलस्टोरेज में मौजूद है या नहीं करता है, आप इसे सेट कर सकते हैं। मुझे लगता है कि जैसे ही आप इसे प्राप्त करेंगे, एपीआई मॉड्यूल पर टोकन सेट करना सबसे अच्छा होगा।
ध्रुव कुमार झा

1
Dan Abromov यहाँ जारी कतार में एक उदाहरण प्रदान करता है: github.com/reactjs/redux/issues/916
chrisjlee

1
यदि आपको किसी विशेष reducer से किसी विशेष स्थिति तक पहुँचने की आवश्यकता है, तो आप redux-name-reducers के साथ कोशिश कर सकते हैं यह आपको कहीं से भी नवीनतम स्थिति तक पहुँचने की अनुमति देता है।
मील_क्रिस्टियन

जवाबों:


146

आपके द्वारा बुलाए गए मॉड्यूल से स्टोर निर्यात करें createStore। फिर आप आश्वस्त हैं कि यह दोनों बनाया जाएगा और वैश्विक विंडो स्थान को प्रदूषित नहीं करेगा।

MyStore.js

const store = createStore(myReducer);
export store;

या

const store = createStore(myReducer);
export default store;

MyClient.js

import {store} from './MyStore'
store.dispatch(...)

या यदि आपने डिफ़ॉल्ट का उपयोग किया है

import store from './MyStore'
store.dispatch(...)

एकाधिक स्टोर उपयोग मामलों के लिए

यदि आपको स्टोर के कई उदाहरणों की आवश्यकता है, तो फ़ैक्टरी फ़ंक्शन निर्यात करें। मैं इसे बनाने की सलाह दूंगा async(ए promise) वापस करना ।

async function getUserStore (userId) {
   // check if user store exists and return or create it.
}
export getUserStore

ग्राहक पर (एक asyncब्लॉक में)

import {getUserStore} from './store'

const joeStore = await getUserStore('joe')

47
आइसोमॉर्फिक ऐप्स के लिए चेतावनी: इस सर्वर-साइड को करने से आपके सभी उपयोगकर्ताओं में रिडक्स स्टोर साझा हो जाएगा !!!
लॉरेंस वेगरफील्ड 10

6
यह प्रश्न स्पष्ट रूप से "ब्राउज़र" भी नहीं बताता है। चूंकि Redux और JavaScript दोनों का उपयोग सर्वर या ब्राउज़र पर किया जा सकता है, इसलिए यह विशिष्ट होना अधिक सुरक्षित है।
लॉरेंस वैगरफील्ड

7
निर्यात की दुकान चक्रीय आयातों की एक दुःस्वप्न बनाने के लिए लगता है, createStore में आपके रिड्यूसर शामिल हैं, जिन्हें आपके कार्यों (कम से कम एक्शन टाइप एनम, और एक्शन इंटरफेस) की आवश्यकता होती है, जो कि कुछ भी आयात नहीं करना चाहिए जो स्टोर को आयात करने की कोशिश करता है। इसलिए आपको अपने रेड्यूसर या क्रियाओं में या तो स्टोर का उपयोग नहीं करना चाहिए (या चक्रीय आयात के आसपास किसी अन्य तरीके से कम करना चाहिए।)
एलॉफ

6
यह सही उत्तर है, लेकिन यदि आप (मेरे जैसे) स्टोर में एक एक्शन भेजने के बजाय पढ़ना चाहते हैं, तो आपको कॉल करने की आवश्यकता हैstore.getState()
जुआन जोस रामिरेज़

3
खैर, "एक्सेस रिडक्स स्टोर" पर मेरी व्याख्या स्टोर को "पढ़ना" था। बस दूसरों की मदद करने की कोशिश कर रहा है।
जुआन जोस रामिरेज़

47

एक समाधान मिला। इसलिए मैं अपने एपीआई उपयोग में स्टोर को आयात करता हूं और वहां सदस्यता लेता हूं। और उस श्रोता समारोह में मैंने अपने नए उभरे हुए टोकन के साथ अक्षतंतु की वैश्विक चूक को निर्धारित किया।

यह मेरा नया रूप api.jsहै:

// tooling modules
import axios from 'axios'

// store
import store from '../store'
store.subscribe(listener)

function select(state) {
  return state.auth.tokens.authentication_token
}

function listener() {
  let token = select(store.getState())
  axios.defaults.headers.common['Authorization'] = token;
}

// configuration
const api = axios.create({
  baseURL: 'http://localhost:5001/api/v1',
  headers: {
    'Content-Type': 'application/json',
  }
})

export default api

हो सकता है कि इसमें और सुधार किया जा सके, क्योंकि वर्तमान में यह थोड़ा असमान लगता है। बाद में मैं क्या कर सकता था, मेरे स्टोर में एक मिडलवेयर जोड़ दिया और फिर टोकन सेट किया।


1
क्या आप साझा कर सकते हैं कि आपकी store.jsफ़ाइल कैसी दिखती है?
विक

बिल्कुल कुछ मैं देख रहा था, धन्यवाद a ton @subodh
हरकीरत सलूजा

1
मुझे पता है कि प्रश्न पुराना है, लेकिन आप अपने उत्तर को सही मान सकते हैं। यह आपके उत्तर को दूसरों के लिए ढूंढना आसान बनाता है जो अंततः यहां आ सकते हैं।
फिलिप मर्कर

3
जब मैं किसी घटक या फ़ंक्शन के बाहर स्टोर तक पहुंचने का प्रयास करता हूं, तो मुझे "TypeError: WEBPACK_IMPORTED_MODULE_2__store_js .b अपरिभाषित है" मिला । इस पर कोई मदद क्यों?
बेन

21

आप फ़ंक्शन storeसे दी गई ऑब्जेक्ट का उपयोग कर सकते हैं createStore(जो कि ऐप इनिशियलाइज़ेशन में आपके कोड में पहले से ही उपयोग किया जाना चाहिए)। थान से आप इस वस्तु का उपयोग वर्तमान स्थिति को प्राप्त करने के लिए कर सकते हैं store.getState()या store.subscribe(listener)अपडेट स्टोर करने के लिए सदस्यता ले सकते हैं।

windowयदि आप वास्तव में इसे चाहते हैं तो आप इस ऑब्जेक्ट को आवेदन के किसी भी हिस्से से एक्सेस करने के लिए संपत्ति को बचा सकते हैं ( window.store = store)

अधिक जानकारी Redux प्रलेखन में पाई जा सकती है ।


19
लगता है थोड़े हैक करने के लिए बचाने storeके लिएwindow
विक

3
@Vic ज़रूर है :) और आम तौर पर आप ऐसा नहीं करना चाहते। मैं सिर्फ यह उल्लेख करना चाहता था कि आप इस चर के साथ जो चाहें कर सकते हैं। संभवत: सबसे अच्छा विचार यह होगा कि आप इसे उस फ़ाइल में संग्रहीत करें जहां आपने अपना "createStore" जीवन बनाया और फिर उससे आयात किया।
trashgenerator

मेरे पास कई iframes हैं, जिन्हें अन्य iframes की स्थिति तक पहुंचने की आवश्यकता है। मुझे पता है कि यह थोड़े हैसी है, लेकिन मुझे लगता है कि विंडो पर स्टोर होने से मैसेज का इस्तेमाल आइफ्रेम करने से बेहतर होगा। कोई विचार?? @Vic @trashgenerator?
सीन मैल्टर


9

जैसे @sanchit प्रस्तावित मिडलवेयर एक अच्छा समाधान है यदि आप पहले से ही वैश्विक स्तर पर अपने axios उदाहरण को परिभाषित कर रहे हैं।

आप एक मिडलवेयर बना सकते हैं जैसे:

function createAxiosAuthMiddleware() {
  return ({ getState }) => next => (action) => {
    const { token } = getState().authentication;
    global.axios.defaults.headers.common.Authorization = token ? `Bearer ${token}` : null;

    return next(action);
  };
}

const axiosAuth = createAxiosAuthMiddleware();

export default axiosAuth;

और इसे इस तरह से उपयोग करें:

import { createStore, applyMiddleware } from 'redux';
const store = createStore(reducer, applyMiddleware(axiosAuth))

यह प्रत्येक क्रिया पर एक टोकन सेट करेगा लेकिन आप केवल उन कार्यों के लिए सुन सकते हैं जो उदाहरण के लिए टोकन बदलते हैं।


3

टाइपस्क्रिप्ट 2.0 के लिए यह इस तरह दिखेगा:

MyStore.ts

export namespace Store {

    export type Login = { isLoggedIn: boolean }

    export type All = {
        login: Login
    }
}

import { reducers } from '../Reducers'
import * as Redux from 'redux'

const reduxStore: Redux.Store<Store.All> = Redux.createStore(reducers)

export default reduxStore;

MyClient.tsx

import reduxStore from "../Store";
{reduxStore.dispatch(...)}

3
यदि आप नीचे मतदान कर रहे हैं, तो कृपया एक टिप्पणी जोड़ें।
ओग्लस

3
नीचे मतदान किया गया क्योंकि आपके उत्तर में स्पष्टीकरण का अभाव है और जावास्क्रिप्ट के बजाय टाइपस्क्रिप्ट का उपयोग करता है।
विल

2
@Will ऐसा कहने के लिए धन्यवाद। Imao कोड को विनिर्देशन की आवश्यकता नहीं होती है, लेकिन यदि आप कुछ विशिष्ट चाहते हैं तो कृपया बताएं कि क्या है। टाइपस्क्रिप्ट वास्तव में उपयोग किया जाता है, लेकिन यदि टाइपिंग हटा दी जाती है तो एक ही कोड ES6 में एक समस्या के बिना चलेगा।
ओग्लस

ध्यान रखें यह बहुत बुरा होगा यदि आप गंभीर साइड-रेंडरिंग कर रहे हैं, तो यह सभी अनुरोधों के साथ राज्य साझा करेगा।
रोब इवांस

2

यह थोड़ा देर हो सकता है लेकिन मुझे लगता है कि सबसे अच्छा तरीका axios.interceptorsनीचे के रूप में उपयोग करना है । आपके प्रोजेक्ट सेटअप के आधार पर आयात यूआरएल बदल सकता है।

index.js

import axios from 'axios';
import setupAxios from './redux/setupAxios';
import store from './redux/store';

// some other codes

setupAxios(axios, store);

setupAxios.js

export default function setupAxios(axios, store) {
    axios.interceptors.request.use(
        (config) => {
            const {
                auth: { tokens: { authorization_token } },
            } = store.getState();

            if (authorization_token) {
                config.headers.Authorization = `Bearer ${authorization_token}`;
            }

            return config;
        },
       (err) => Promise.reject(err)
    );
}

1

इसे हुक के साथ करना। मैं एक समान समस्या में भाग गया, लेकिन मैं हुक के साथ प्रतिक्रिया-रिडक्स का उपयोग कर रहा था। मैं अपने इंटरफ़ेस कोड (यानी, घटकों पर प्रतिक्रिया) को बहुत सारे कोड के साथ / स्टोर से जानकारी प्राप्त / भेजने के लिए समर्पित नहीं करना चाहता था। बल्कि, मैं डेटा को पुनः प्राप्त करने और अद्यतन करने के लिए सामान्य नामों के साथ फ़ंक्शन चाहता था। मेरा रास्ता ऐप को डालना था

const store = createSore(
   allReducers,
   window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
 );

नामित मॉड्यूल में store.jsऔर exportपहले जोड़ने constऔर store.js में सामान्य प्रतिक्रिया-रिडक्स आयात को जोड़ना। फ़ाइल। फिर, मैंने index.jsऐप स्तर पर आयात किया , जिसे मैंने सामान्य रूप से index.js में आयात किया import {store} from "./store.js"। बाल घटकों ने तब useSelector()और useDispatch()हुक का उपयोग करके स्टोर तक पहुंच बनाई।

गैर-घटक फ्रंट एंड कोड में स्टोर तक पहुंचने के लिए, मैंने स्टोर के अनुरूप आयात (यानी, import {store} from "../../store.js") का उपयोग किया store.getState()और फिर उपयोग store.dispatch({*action goes here*})और अपडेट (एर, भेजने की क्रिया) को संभाला और संभाला।


0

टोकन तक पहुंच का एक आसान तरीका है, लोकलस्टेज में टोकन को डालना या रिएक्टिव रिलेटिव के साथ एसिंक्स्टस्टोरेज।

एक प्रतिक्रियाशील मूल परियोजना के साथ एक उदाहरण के नीचे

authReducer.js

import { AsyncStorage } from 'react-native';
...
const auth = (state = initialState, action) => {
  switch (action.type) {
    case SUCCESS_LOGIN:
      AsyncStorage.setItem('token', action.payload.token);
      return {
        ...state,
        ...action.payload,
      };
    case REQUEST_LOGOUT:
      AsyncStorage.removeItem('token');
      return {};
    default:
      return state;
  }
};
...

तथा api.js

import axios from 'axios';
import { AsyncStorage } from 'react-native';

const defaultHeaders = {
  'Content-Type': 'application/json',
};

const config = {
  ...
};

const request = axios.create(config);

const protectedRequest = options => {
  return AsyncStorage.getItem('token').then(token => {
    if (token) {
      return request({
        headers: {
          ...defaultHeaders,
          Authorization: `Bearer ${token}`,
        },
        ...options,
      });
    }
    return new Error('NO_TOKEN_SET');
  });
};

export { request, protectedRequest };

वेब के लिए आप Window.localStorageAsyncStorage के बजाय उपयोग कर सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.