फ्लक्स आर्किटेक्चर में, आप स्टोर जीवनचक्र का प्रबंधन कैसे करते हैं?


132

मैं फ्लक्स के बारे में पढ़ रहा हूं, लेकिन कुछ प्रमुख बिंदुओं को समझने के लिए टोडो ऐप मेरे लिए बहुत सरल है।

फेसबुक जैसे सिंगल-पेज ऐप की कल्पना करें जिसमें उपयोगकर्ता प्रोफ़ाइल पृष्ठ हैं । प्रत्येक उपयोगकर्ता प्रोफ़ाइल पृष्ठ पर, हम अनंत स्क्रॉल के साथ कुछ उपयोगकर्ता जानकारी और उनके अंतिम पोस्ट दिखाना चाहते हैं। हम एक उपयोगकर्ता प्रोफ़ाइल से दूसरे में नेविगेट कर सकते हैं।

फ्लक्स वास्तुकला में, यह स्टोर और डिस्पैचर के अनुरूप कैसे होगा?

क्या हम PostStoreप्रति उपयोगकर्ता एक का उपयोग करेंगे , या हमारे पास किसी प्रकार का वैश्विक स्टोर होगा? डिस्पैचर्स के बारे में, क्या हम प्रत्येक "उपयोगकर्ता पृष्ठ" के लिए एक नया डिस्पैचर बनाएंगे, या हम एक सिंगलटन का उपयोग करेंगे? अंत में, मार्ग परिवर्तन के जवाब में "पृष्ठ-विशिष्ट" स्टोर्स के जीवन चक्र के प्रबंधन के लिए वास्तुकला का कौन सा हिस्सा जिम्मेदार है?

इसके अलावा, एक एकल छद्म पृष्ठ में एक ही प्रकार के डेटा की कई सूचियाँ हो सकती हैं। उदाहरण के लिए, एक प्रोफाइल पेज पर, मैं दोनों दिखाना चाहते हैं समर्थक और अनुसरण करता हैUserStoreइस मामले में एक सिंगलटन कैसे काम कर सकता है ? UserPageStoreप्रबंधन followedBy: UserStoreऔर होगा follows: UserStore?

जवाबों:


124

एक फ्लक्स ऐप में केवल एक डिस्पैचर होना चाहिए। सारा डेटा इस सेंट्रल हब से होकर बहता है। एक सिंगलटन डिस्पैचर होने से यह सभी स्टोर्स को प्रबंधित करने की अनुमति देता है। यह तब महत्वपूर्ण हो जाता है जब आपको स्टोर # 1 अपडेट की आवश्यकता होती है, और उसके बाद स्टोर # 2 अपडेट खुद एक्शन और स्टोर 1 की स्थिति पर आधारित होता है। फ्लक्स मानता है कि यह स्थिति एक बड़े अनुप्रयोग में एक घटना है। आदर्श रूप से इस स्थिति को होने की आवश्यकता नहीं होगी, और डेवलपर्स को यदि संभव हो तो इस जटिलता से बचने का प्रयास करना चाहिए। लेकिन सिंगलटन डिस्पैचर समय आने पर इसे संभालने के लिए तैयार है।

भंडार एकल के रूप में अच्छी तरह से कर रहे हैं। उन्हें यथासंभव स्वतंत्र और डिकॉउन्ड रहना चाहिए - एक आत्म-निहित ब्रह्मांड जिसे कोई नियंत्रक-दृश्य से क्वेरी कर सकता है। स्टोर में एकमात्र सड़क कॉलबैक के माध्यम से है जो डिस्पैचर के साथ पंजीकृत है। गेटवे फ़ंक्शंस के माध्यम से एकमात्र सड़क बाहर है। स्टोर एक घटना को भी प्रकाशित करते हैं जब उनका राज्य बदल गया है, इसलिए नियंत्रक-दृश्य यह जान सकते हैं कि गेट्स का उपयोग करके नए राज्य के लिए कब क्वेरी करना है।

आपके उदाहरण एप्लिकेशन में, एक एकल होगा PostStore। यह वही स्टोर एक "पृष्ठ" (छद्म पृष्ठ) पर पदों का प्रबंधन कर सकता है जो एफबी के न्यूजफीड की तरह है, जहां विभिन्न उपयोगकर्ताओं से पोस्ट दिखाई देते हैं। इसका तार्किक डोमेन पदों की सूची है, और यह पदों की किसी भी सूची को संभाल सकता है। जब हम छद्म पृष्ठ से छद्म पृष्ठ पर जाते हैं, तो हम नए राज्य को प्रतिबिंबित करने के लिए स्टोर की स्थिति को फिर से संगठित करना चाहते हैं। हम छद्म पन्नों के बीच आगे और पीछे जाने के लिए एक अनुकूलन के रूप में लोकलस्टोरेज में पिछली स्थिति को कैश करना चाहते हैं, लेकिन मेरा झुकाव PageStoreअन्य सभी स्टोरों के लिए इंतजार करना होगा , सभी दुकानों पर लोकलस्टोरेज के साथ संबंधों का प्रबंधन करता है छद्म पृष्ठ, और उसके बाद अपनी स्थिति को अद्यतन करता है। ध्यान दें कि यह PageStoreपदों के बारे में कुछ भी संग्रहीत नहीं करेगा - यह डोमेन हैPostStore। यह आसानी से पता चल जाएगा कि किसी विशेष छद्म पृष्ठ को कैश किया गया है या नहीं, क्योंकि छद्म पृष्ठ इसके डोमेन हैं।

PostStoreएक होता है initialize()विधि। यह विधि हमेशा पुरानी स्थिति को साफ़ कर देगी, भले ही यह पहला आरंभीकरण हो, और फिर डिस्पैचर के माध्यम से एक्शन के माध्यम से प्राप्त डेटा के आधार पर राज्य का निर्माण करें। एक छद्म पृष्ठ से दूसरे में जाना संभवतः एक PAGE_UPDATEकार्रवाई को शामिल करेगा, जो के आह्वान को ट्रिगर करेगा initialize()। स्थानीय कैश से डेटा प्राप्त करने, सर्वर से डेटा पुनः प्राप्त करने, आशावादी प्रतिपादन और एक्सएचआर त्रुटि राज्यों के आसपास काम करने के लिए विवरण हैं, लेकिन यह सामान्य विचार है।

यदि किसी विशेष छद्म पृष्ठ को एप्लिकेशन के सभी स्टोर की आवश्यकता नहीं है, तो मुझे पूरी तरह से यकीन नहीं है कि अप्रयुक्त लोगों को नष्ट करने का कोई कारण है, स्मृति बाधाओं के अलावा। लेकिन स्टोर आमतौर पर मेमोरी का बहुत अधिक उपभोग नहीं करते हैं। आपको बस नियंत्रक-दृश्य में मौजूद श्रोताओं को निकालना सुनिश्चित करना होगा, जिसे आप नष्ट कर रहे हैं। यह रिएक्ट की componentWillUnmount()विधि में किया जाता है ।


5
निश्चित रूप से कुछ अलग दृष्टिकोण हैं जो आप करना चाहते हैं, और मुझे लगता है कि यह इस बात पर निर्भर करता है कि आप क्या बनाने की कोशिश कर रहे हैं। एक दृष्टिकोण एक होगा UserListStore, जिसमें सभी प्रासंगिक उपयोगकर्ता होंगे। और प्रत्येक उपयोगकर्ता के पास वर्तमान उपयोगकर्ता प्रोफ़ाइल के संबंध का वर्णन करने वाले बूलियन झंडे के एक जोड़े होंगे। जैसे कुछ { follower: true, followed: false }, उदाहरण के लिए। तरीके getFolloweds()और getFollowers()यूआई के लिए आवश्यक उपयोगकर्ताओं के विभिन्न सेटों को पुनः प्राप्त करेंगे।
फिशरदेबदेव

4
वैकल्पिक रूप से, आपके पास एक FollowedUserListStore और एक FollowerUserListStore हो सकता है, जो दोनों को एक अमूर्त UserListStore से विरासत में मिला है।
फिशरदेबदेव

मेरा एक छोटा सा सवाल है - क्यों नहीं ग्राहकों को डेटा पुनः प्राप्त करने की आवश्यकता के बजाय सीधे दुकानों से डेटा का उत्सर्जन करने के लिए पब उप का उपयोग करना चाहिए?
सनवुकुंग

2
@sunwukung स्टोर को यह नियंत्रित करने की आवश्यकता होगी कि नियंत्रक-विचारों को किस डेटा की आवश्यकता है। दुकानों में इस तथ्य को प्रकाशित करने के लिए यह क्लीनर है कि वे किसी तरह से बदल गए हैं, और फिर रुचि नियंत्रक-विचारों को पुनः प्राप्त करें कि उन्हें डेटा के किन हिस्सों की आवश्यकता है।
फिशरदेबदेव

क्या होगा यदि मेरे पास एक प्रोफ़ाइल पृष्ठ है जहां मैं एक उपयोगकर्ता के बारे में जानकारी दिखाता हूं, लेकिन उसके दोस्तों की सूची भी। उपयोगकर्ता और मित्र दोनों एक ही प्रकार के होंगे। अगर वे एक ही दुकान में रहना चाहिए तो?
निक

79

(नोट: मैंने JSX हार्मनी विकल्प का उपयोग करके ES6 सिंटैक्स का उपयोग किया है।)

एक अभ्यास के रूप में, मैंने एक नमूना फ्लक्स ऐप लिखा है जो ब्राउज़ करने Github usersऔर रिपोज करने की अनुमति देता है ।
यह फिशरदेबदेव के उत्तर पर आधारित है, लेकिन एपीआई प्रतिक्रियाओं को सामान्य करने के लिए मेरे द्वारा उपयोग किए जाने वाले दृष्टिकोण को भी दर्शाता है।

मैंने फ्लक्स सीखते हुए कुछ दृष्टिकोणों को दस्तावेज करने के लिए इसे बनाया है।
मैंने इसे वास्तविक दुनिया के करीब रखने की कोशिश की (पेजिनेशन, कोई नकली लोकलस्टोरी एपीआई नहीं)।

यहाँ कुछ बिट्स हैं जिन्हें मैं विशेष रूप से दिलचस्पी लेता था:

कैसे मैं स्टोर वर्गीकृत

मैंने कुछ प्रवाह से बचने की कोशिश की है जो मैंने अन्य फ्लक्स उदाहरण में देखा है, विशेष रूप से स्टोर्स में। मुझे स्टोर को तार्किक रूप से तीन श्रेणियों में विभाजित करना उपयोगी लगा:

कंटेंट स्टोर्स सभी ऐप एंटिटीज़ को होल्ड करते हैं। जिस चीज के लिए ID होती है, उसे अपने Content Store की आवश्यकता होती है। व्यक्तिगत आइटम रेंडर करने वाले घटक ताज़ा डेटा के लिए सामग्री स्टोर से पूछते हैं।

सामग्री स्टोर सभी सर्वर क्रियाओं से अपनी वस्तुओं की कटाई करते हैं । उदाहरण के लिए, यह UserStore देखता हैaction.response.entities.users कि क्या मौजूद है, भले ही कार्रवाई निकाल दी गई हो। इसके लिए कोई जरूरत नहीं है switchNormalizr इस प्रारूप में किसी भी एपीआई रिपॉन्स को समतल करना आसान बनाता है।

// Content Stores keep their data like this
{
  7: {
    id: 7,
    name: 'Dan'
  },
  ...
}

सूची भंडार कुछ वैश्विक सूची (जैसे "फ़ीड", "आपकी सूचनाएँ") में दिखाई देने वाली संस्थाओं की आईडी पर नज़र रखते हैं। इस परियोजना में, मेरे पास ऐसे स्टोर नहीं हैं, लेकिन मैंने सोचा था कि मैं उनका उल्लेख करूंगा। वे पग-पग संभालते हैं।

वे आम तौर पर बस कुछ ही कार्रवाई का जवाब (जैसे REQUEST_FEED, REQUEST_FEED_SUCCESS, REQUEST_FEED_ERROR)।

// Paginated Stores keep their data like this
[7, 10, 5, ...]

अनुक्रमित सूची भंडार सूची भंडार की तरह हैं लेकिन वे एक-से-कई संबंधों को परिभाषित करते हैं। उदाहरण के लिए, "उपयोगकर्ता के ग्राहक", "रिपोजिटरी के स्टारगेज़र्स", "उपयोगकर्ता के रिपॉजिटरी"। वे भी अंकुरण संभालते हैं।

उन्होंने यह भी सामान्य रूप से बस कुछ ही कार्रवाई का जवाब (जैसे REQUEST_USER_REPOS, REQUEST_USER_REPOS_SUCCESS, REQUEST_USER_REPOS_ERROR)।

अधिकांश सामाजिक ऐप्स में, आपके पास इनमें से बहुत सारे होंगे और आप उनमें से एक को जल्दी से बनाने में सक्षम होना चाहते हैं।

// Indexed Paginated Stores keep their data like this
{
  2: [7, 10, 5, ...],
  6: [7, 1, 2, ...],
  ...
}

नोट: ये वास्तविक वर्ग या कुछ नहीं हैं; यह सिर्फ मैं कैसे स्टोर के बारे में सोचना पसंद है। मैंने हालांकि कुछ मदद की।

StoreUtils

createStore

यह विधि आपको सबसे मूल स्टोर देती है:

createStore(spec) {
  var store = merge(EventEmitter.prototype, merge(spec, {
    emitChange() {
      this.emit(CHANGE_EVENT);
    },

    addChangeListener(callback) {
      this.on(CHANGE_EVENT, callback);
    },

    removeChangeListener(callback) {
      this.removeListener(CHANGE_EVENT, callback);
    }
  }));

  _.each(store, function (val, key) {
    if (_.isFunction(val)) {
      store[key] = store[key].bind(store);
    }
  });

  store.setMaxListeners(0);
  return store;
}

मैं इसका उपयोग सभी स्टोर बनाने के लिए करता हूं।

isInBag, mergeIntoBag

सामग्री भंडार के लिए उपयोगी छोटे सहायक।

isInBag(bag, id, fields) {
  var item = bag[id];
  if (!bag[id]) {
    return false;
  }

  if (fields) {
    return fields.every(field => item.hasOwnProperty(field));
  } else {
    return true;
  }
},

mergeIntoBag(bag, entities, transform) {
  if (!transform) {
    transform = (x) => x;
  }

  for (var key in entities) {
    if (!entities.hasOwnProperty(key)) {
      continue;
    }

    if (!bag.hasOwnProperty(key)) {
      bag[key] = transform(entities[key]);
    } else if (!shallowEqual(bag[key], entities[key])) {
      bag[key] = transform(merge(bag[key], entities[key]));
    }
  }
}

PaginatedList

स्टोर पेजेशन स्टेट और कुछ कथनों को लागू करता है (जब तक, इत्यादि लाने के लिए पेज नहीं लाया जा सकता)।

class PaginatedList {
  constructor(ids) {
    this._ids = ids || [];
    this._pageCount = 0;
    this._nextPageUrl = null;
    this._isExpectingPage = false;
  }

  getIds() {
    return this._ids;
  }

  getPageCount() {
    return this._pageCount;
  }

  isExpectingPage() {
    return this._isExpectingPage;
  }

  getNextPageUrl() {
    return this._nextPageUrl;
  }

  isLastPage() {
    return this.getNextPageUrl() === null && this.getPageCount() > 0;
  }

  prepend(id) {
    this._ids = _.union([id], this._ids);
  }

  remove(id) {
    this._ids = _.without(this._ids, id);
  }

  expectPage() {
    invariant(!this._isExpectingPage, 'Cannot call expectPage twice without prior cancelPage or receivePage call.');
    this._isExpectingPage = true;
  }

  cancelPage() {
    invariant(this._isExpectingPage, 'Cannot call cancelPage without prior expectPage call.');
    this._isExpectingPage = false;
  }

  receivePage(newIds, nextPageUrl) {
    invariant(this._isExpectingPage, 'Cannot call receivePage without prior expectPage call.');

    if (newIds.length) {
      this._ids = _.union(this._ids, newIds);
    }

    this._isExpectingPage = false;
    this._nextPageUrl = nextPageUrl || null;
    this._pageCount++;
  }
}

PaginatedStoreUtils

createListStore, createIndexedListStore,createListActionHandler

बॉयलरप्लेट विधियों और कार्रवाई से निपटने के द्वारा संभव के रूप में सरल के रूप में अनुक्रमित सूची भंडार का निर्माण करता है:

var PROXIED_PAGINATED_LIST_METHODS = [
  'getIds', 'getPageCount', 'getNextPageUrl',
  'isExpectingPage', 'isLastPage'
];

function createListStoreSpec({ getList, callListMethod }) {
  var spec = {
    getList: getList
  };

  PROXIED_PAGINATED_LIST_METHODS.forEach(method => {
    spec[method] = function (...args) {
      return callListMethod(method, args);
    };
  });

  return spec;
}

/**
 * Creates a simple paginated store that represents a global list (e.g. feed).
 */
function createListStore(spec) {
  var list = new PaginatedList();

  function getList() {
    return list;
  }

  function callListMethod(method, args) {
    return list[method].call(list, args);
  }

  return createStore(
    merge(spec, createListStoreSpec({
      getList: getList,
      callListMethod: callListMethod
    }))
  );
}

/**
 * Creates an indexed paginated store that represents a one-many relationship
 * (e.g. user's posts). Expects foreign key ID to be passed as first parameter
 * to store methods.
 */
function createIndexedListStore(spec) {
  var lists = {};

  function getList(id) {
    if (!lists[id]) {
      lists[id] = new PaginatedList();
    }

    return lists[id];
  }

  function callListMethod(method, args) {
    var id = args.shift();
    if (typeof id ===  'undefined') {
      throw new Error('Indexed pagination store methods expect ID as first parameter.');
    }

    var list = getList(id);
    return list[method].call(list, args);
  }

  return createStore(
    merge(spec, createListStoreSpec({
      getList: getList,
      callListMethod: callListMethod
    }))
  );
}

/**
 * Creates a handler that responds to list store pagination actions.
 */
function createListActionHandler(actions) {
  var {
    request: requestAction,
    error: errorAction,
    success: successAction,
    preload: preloadAction
  } = actions;

  invariant(requestAction, 'Pass a valid request action.');
  invariant(errorAction, 'Pass a valid error action.');
  invariant(successAction, 'Pass a valid success action.');

  return function (action, list, emitChange) {
    switch (action.type) {
    case requestAction:
      list.expectPage();
      emitChange();
      break;

    case errorAction:
      list.cancelPage();
      emitChange();
      break;

    case successAction:
      list.receivePage(
        action.response.result,
        action.response.nextPageUrl
      );
      emitChange();
      break;
    }
  };
}

var PaginatedStoreUtils = {
  createListStore: createListStore,
  createIndexedListStore: createIndexedListStore,
  createListActionHandler: createListActionHandler
};

createStoreMixin

एक मिश्रण जो घटकों को स्टोर करने के लिए ट्यून करने की अनुमति देता है, जिसमें वे रुचि रखते हैं, जैसे mixins: [createStoreMixin(UserStore)]

function createStoreMixin(...stores) {
  var StoreMixin = {
    getInitialState() {
      return this.getStateFromStores(this.props);
    },

    componentDidMount() {
      stores.forEach(store =>
        store.addChangeListener(this.handleStoresChanged)
      );

      this.setState(this.getStateFromStores(this.props));
    },

    componentWillUnmount() {
      stores.forEach(store =>
        store.removeChangeListener(this.handleStoresChanged)
      );
    },

    handleStoresChanged() {
      if (this.isMounted()) {
        this.setState(this.getStateFromStores(this.props));
      }
    }
  };

  return StoreMixin;
}

1
इस तथ्य को देखते हुए कि आपने स्टैम्पी लिखी है, यदि आप पूरे क्लाइंट साइड एप्लिकेशन को फिर से लिखेंगे, तो क्या आप इस उदाहरण ऐप के निर्माण के लिए FLUX और उसी दृष्टिकोण का उपयोग करेंगे?
ईएबी

2
eAbi: यह वह तरीका है जिसका हम वर्तमान में उपयोग कर रहे हैं क्योंकि हम स्टैम्पसी को फ्लक्स में फिर से लिख रहे हैं (अगले महीने इसे जारी करने की उम्मीद है)। यह आदर्श नहीं है लेकिन यह हमारे लिए अच्छा काम करता है। जब / यदि हम उस सामान को करने के बेहतर तरीके का पता लगाते हैं, तो हम उन्हें साझा करेंगे।
डैन अब्रामोव

1
eAbi: हालाँकि हम अब normalizr का उपयोग नहीं करते हैं क्योंकि एक आदमी हमारी टीम ने सामान्यीकृत प्रतिक्रियाओं को वापस करने के लिए हमारे सभी API को फिर से लिखा है । हालांकि इससे पहले यह उपयोगी था।
दान अब्रामोव

आपकी जानकारी के लिए धन्यवाद। मैंने आपके गिथब रेपो की जाँच की है और मैं आपके दृष्टिकोण के साथ एक परियोजना (YUI3 में निर्मित) शुरू करने की कोशिश कर रहा हूँ, लेकिन मुझे कोड को संकलित करने में कुछ परेशानी हो रही है (यदि आप ऐसा कह सकते हैं)। मैं नोड के तहत सर्वर नहीं चला रहा हूं, इसलिए मैं स्रोत को अपनी स्थिर निर्देशिका में कॉपी करना चाहता था, लेकिन मुझे अभी भी कुछ काम करना है ... यह थोड़ा बोझिल है, और इसके अलावा, मुझे कुछ फाइलें अलग-अलग जेएस सिंटैक्स वाली मिलीं। खासकर jsx फाइलों में।
ईएबी

2
@ सीन: मैं इसे एक समस्या के रूप में नहीं देखता। डाटा प्रवाह डेटा लेखन, यह पढ़ नहीं के बारे में है। यकीन है कि यह सबसे अच्छा है अगर कार्रवाई दुकानों के अज्ञेयवादी हैं, लेकिन अनुरोधों के अनुकूलन के लिए मुझे लगता है कि यह दुकानों से पढ़ने के लिए पूरी तरह से ठीक है। आखिरकार, घटक स्टोर से पढ़ते हैं और उन कार्यों को आग लगाते हैं। आप इस तर्क को हर घटक में दोहरा सकते हैं, लेकिन यही क्रिया रचनाकार के लिए है ..
Dan Abramov

27

इसलिए रिफ्लक्स में डिस्पैचर की अवधारणा को हटा दिया गया है और आपको केवल क्रियाओं और दुकानों के माध्यम से डेटा प्रवाह के बारे में सोचने की आवश्यकता है। अर्थात

Actions <-- Store { <-- Another Store } <-- Components

यहां प्रत्येक तीर मॉडल करता है कि डेटा प्रवाह को कैसे सुना जाता है, जिसका अर्थ है कि डेटा विपरीत दिशा में बहता है। डेटा प्रवाह का वास्तविक आंकड़ा यह है:

Actions --> Stores --> Components
   ^          |            |
   +----------+------------+

आपके उपयोग के मामले में, अगर मुझे सही ढंग से समझ में आया, तो हमें एक ऐसी openUserProfileकार्रवाई की आवश्यकता है जो उपयोगकर्ता प्रोफ़ाइल लोड करने और पृष्ठ को स्विच करने की पहल करे और कुछ पोस्ट लोड करने वाली क्रियाएं भी करें जो उपयोगकर्ता प्रोफ़ाइल पृष्ठ को खोलने और अनंत स्क्रॉल इवेंट के दौरान पोस्ट लोड करेगी। इसलिए मुझे लगता है कि हमारे पास आवेदन में निम्नलिखित डेटा स्टोर हैं:

  • एक पृष्ठ डेटा स्टोर जो स्विचिंग पृष्ठों को संभालता है
  • एक उपयोगकर्ता प्रोफ़ाइल डेटा स्टोर जो पेज खुलने पर उपयोगकर्ता प्रोफ़ाइल लोड करता है
  • एक पोस्ट डेटा स्टोर को सूचीबद्ध करता है जो दृश्यमान पदों को लोड और संभालता है

रिफ्लक्स में आप इसे इस तरह सेट करेंगे:

क्रियाएँ

// Set up the two actions we need for this use case.
var Actions = Reflux.createActions(['openUserProfile', 'loadUserProfile', 'loadInitialPosts', 'loadMorePosts']);

पेज की दुकान

var currentPageStore = Reflux.createStore({
    init: function() {
        this.listenTo(openUserProfile, this.openUserProfileCallback);
    },
    // We are assuming that the action is invoked with a profileid
    openUserProfileCallback: function(userProfileId) {
        // Trigger to the page handling component to open the user profile
        this.trigger('user profile');

        // Invoke the following action with the loaded the user profile
        Actions.loadUserProfile(userProfileId);
    }
});

उपयोगकर्ता प्रोफ़ाइल स्टोर

var currentUserProfileStore = Reflux.createStore({
    init: function() {
        this.listenTo(Actions.loadUserProfile, this.switchToUser);
    },
    switchToUser: function(userProfileId) {
        // Do some ajaxy stuff then with the loaded user profile
        // trigger the stores internal change event with it
        this.trigger(userProfile);
    }
});

पदों की दुकान

var currentPostsStore = Reflux.createStore({
    init: function() {
        // for initial posts loading by listening to when the 
        // user profile store changes
        this.listenTo(currentUserProfileStore, this.loadInitialPostsFor);
        // for infinite posts loading
        this.listenTo(Actions.loadMorePosts, this.loadMorePosts);
    },
    loadInitialPostsFor: function(userProfile) {
        this.currentUserProfile = userProfile;

        // Do some ajax stuff here to fetch the initial posts then send
        // them through the change event
        this.trigger(postData, 'initial');
    },
    loadMorePosts: function() {
        // Do some ajaxy stuff to fetch more posts then send them through
        // the change event
        this.trigger(postData, 'more');
    }
});

अवयव

मैं मान रहा हूं कि आपके पास पूरे पृष्ठ दृश्य, उपयोगकर्ता प्रोफ़ाइल पृष्ठ और पोस्ट सूची के लिए एक घटक है। निम्नलिखित को तार-तार करने की आवश्यकता है:

  • उपयोगकर्ता प्रोफ़ाइल खोलने वाले बटन पर Action.openUserProfileक्लिक ईवेंट के दौरान सही आईडी के साथ आह्वान करने की आवश्यकता होती है ।
  • पृष्ठ घटक को सुनना चाहिए currentPageStoreताकि यह पता चले कि किस पृष्ठ पर स्विच करना है।
  • उपयोगकर्ता प्रोफ़ाइल पृष्ठ घटक को सुनने की आवश्यकता है currentUserProfileStoreताकि यह पता चले कि उपयोगकर्ता प्रोफ़ाइल डेटा क्या दिखाना है
  • currentPostsStoreलोड किए गए पदों को प्राप्त करने के लिए पदों की सूची को सुनने की जरूरत है
  • अनंत स्क्रॉल इवेंट को कॉल करने की आवश्यकता है Action.loadMorePosts

और यह बहुत ज्यादा होना चाहिए।


अद्यतित करने के लिए धन्यवाद!
दान अब्रामोव

2
पार्टी के लिए थोड़ा देर हो सकती है, लेकिन यहां एक अच्छा लेख है जिसमें बताया गया है कि आप सीधे स्टोर्स से एपीआई कॉल करने से क्यों बचें । मैं अभी भी यह पता लगा रहा हूं कि सबसे अच्छी प्रथाएं क्या हैं, लेकिन मुझे लगा कि यह इस पर ठोकर खाने में मदद कर सकता है। दुकानों के संबंध में कई अलग-अलग दृष्टिकोण चल रहे हैं।
थिजे कोर्सलमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.