किस स्तर पर घटकों को फ्लक्स में स्टोर से संस्थाओं को पढ़ना चाहिए?


89

मैं फ्लक्स का उपयोग करने के लिए अपने ऐप को फिर से लिख रहा हूं और मेरे पास स्टोर से डेटा प्राप्त करने के साथ एक समस्या है। मेरे पास बहुत सारे घटक हैं, और वे बहुत घोंसला बनाते हैं। उनमें से कुछ बड़े हैं ( Article), कुछ छोटे और सरल ( UserAvatar, UserLink) हैं।

मैं उस घटक के साथ संघर्ष कर रहा हूं जहां मुझे स्टोर से डेटा पढ़ना चाहिए।
मैंने दो चरम दृष्टिकोणों की कोशिश की, जिनमें से कोई भी मुझे पसंद नहीं आया:

सभी इकाई घटक अपने स्वयं के डेटा को पढ़ते हैं

प्रत्येक घटक जिसे स्टोर से कुछ डेटा की आवश्यकता होती है, वह केवल एंटिटी आईडी प्राप्त करता है और अपने आप ही इकाई को पुनः प्राप्त करता है।
उदाहरण के लिए, Articleपारित किया जाता है articleId, UserAvatarऔर UserLinkपारित किया जाता है userId

इस दृष्टिकोण में कई महत्वपूर्ण डाउनसाइड हैं (कोड नमूने के तहत चर्चा की गई)।

var Article = React.createClass({
  mixins: [createStoreMixin(ArticleStore)],

  propTypes: {
    articleId: PropTypes.number.isRequired
  },

  getStateFromStores() {
    return {
      article: ArticleStore.get(this.props.articleId);
    }
  },

  render() {
    var article = this.state.article,
        userId = article.userId;

    return (
      <div>
        <UserLink userId={userId}>
          <UserAvatar userId={userId} />
        </UserLink>

        <h1>{article.title}</h1>
        <p>{article.text}</p>

        <p>Read more by <UserLink userId={userId} />.</p>
      </div>
    )
  }
});

var UserAvatar = React.createClass({
  mixins: [createStoreMixin(UserStore)],

  propTypes: {
    userId: PropTypes.number.isRequired
  },

  getStateFromStores() {
    return {
      user: UserStore.get(this.props.userId);
    }
  },

  render() {
    var user = this.state.user;

    return (
      <img src={user.thumbnailUrl} />
    )
  }
});

var UserLink = React.createClass({
  mixins: [createStoreMixin(UserStore)],

  propTypes: {
    userId: PropTypes.number.isRequired
  },

  getStateFromStores() {
    return {
      user: UserStore.get(this.props.userId);
    }
  },

  render() {
    var user = this.state.user;

    return (
      <Link to='user' params={{ userId: this.props.userId }}>
        {this.props.children || user.name}
      </Link>
    )
  }
});

इस दृष्टिकोण के डाउनसाइड्स:

  • यह स्टोर करने के लिए संभावित रूप से 100s घटकों की निराशा होती है;
  • यह जानना मुश्किल है कि डेटा कैसे और किस क्रम में अपडेट किया गया है क्योंकि प्रत्येक घटक अपने डेटा को स्वतंत्र रूप से प्राप्त करता है;
  • भले ही आपके पास पहले से ही राज्य में एक इकाई हो , आप बच्चों को इसकी आईडी पास करने के लिए मजबूर होते हैं, जो इसे फिर से प्राप्त करेंगे (या संगति को तोड़ दें)।

सभी डेटा को शीर्ष स्तर पर एक बार पढ़ा जाता है और घटकों को पास कर दिया जाता है

जब मैं बग्स पर नज़र रखने से थक गया था, मैंने शीर्ष स्तर पर पुनर्प्राप्त सभी डेटा डालने की कोशिश की। यह, हालांकि, असंभव साबित हुआ क्योंकि कुछ संस्थाओं के लिए मेरे पास घोंसले के शिकार के कई स्तर हैं।

उदाहरण के लिए:

  • Categoryमें UserAvatarऐसे लोग शामिल हैं जो उस श्रेणी में योगदान करते हैं;
  • एक Articleकई Categoryएस हो सकता है ।

इसलिए अगर मैं स्टोर के स्तर से सभी डेटा को पुनः प्राप्त करना चाहता था, तो मुझे निम्नलिखित की Articleआवश्यकता होगी:

  • से लेख प्राप्त किया ArticleStore;
  • से सभी लेख की श्रेणियों को पुनः प्राप्त करें CategoryStore;
  • प्रत्येक श्रेणी के योगदानकर्ताओं को अलग से पुनर्प्राप्त करें UserStore;
  • किसी तरह वह सारा डेटा कंपोनेंट्स को डाउन कर देते हैं।

इससे भी अधिक निराशा की बात यह है कि जब भी मुझे एक गहरी नेस्टेड इकाई की आवश्यकता होती है, मुझे घोंसले के प्रत्येक स्तर पर कोड जोड़ने की आवश्यकता होती है ताकि इसके अतिरिक्त इसे नीचे पारित किया जा सके।

उपसंहार

दोनों दृष्टिकोण त्रुटिपूर्ण लगते हैं। मैं इस समस्या को सबसे सुरुचिपूर्ण ढंग से कैसे हल करूं?

मेरे उद्देश्य:

  • स्टोर में ग्राहकों की एक पागल संख्या नहीं होनी चाहिए। यह UserLinkसुनने के लिए प्रत्येक के लिए बेवकूफी UserStoreहै कि क्या मूल घटक पहले से ही ऐसा करते हैं।

  • अगर मूल घटक को स्टोर से कुछ ऑब्जेक्ट (जैसे user) प्राप्त किया गया है, तो मैं नहीं चाहता कि किसी भी नेस्टेड घटक को फिर से लाना पड़े। मैं इसे सहारा के माध्यम से पारित करने में सक्षम होना चाहिए।

  • मुझे शीर्ष स्तर पर सभी संस्थाओं (रिश्तों सहित) को नहीं लाना चाहिए क्योंकि यह रिश्तों को जोड़ने या हटाने में कठिनाई होगी। मैं हर बार सभी घोंसले के शिकार के स्तर पर नए प्रॉप्स को पेश नहीं करना चाहता हूं, जब एक नेस्टेड इकाई को एक नया रिश्ता मिलता है (जैसे श्रेणी ए मिलती है curator)।


1
इसे पोस्ट करने के लिए धन्यवाद। मैंने अभी यहां एक बहुत ही समान प्रश्न पोस्ट किया है: group.google.com/forum/… मैंने जो कुछ भी देखा है वह संबद्ध डेटा के बजाय फ्लैट डेटा संरचनाओं से निपटा है। मुझे आश्चर्य है कि इस पर कोई सर्वोत्तम अभ्यास नहीं देखा।
जुबेरलामा

जवाबों:


37

अधिकांश लोग पदानुक्रम के शीर्ष के पास नियंत्रक-दृश्य घटक में संबंधित स्टोर को सुनकर शुरू करते हैं।

बाद में, जब ऐसा लगता है कि बहुत सारे अप्रासंगिक प्रॉप्स को पदानुक्रम के माध्यम से कुछ गहराई से नेस्टेड घटक में पारित किया जा रहा है, तो कुछ लोग तय करेंगे कि स्टोर में बदलाव के लिए एक गहरे घटक को सुनने के लिए एक अच्छा विचार है। यह समस्या डोमेन का एक बेहतर एनकैप्सुलेशन प्रदान करता है जो घटक ट्री की इस गहरी शाखा के बारे में है। इसे विवेकपूर्ण तरीके से करने के लिए अच्छे तर्क दिए जा रहे हैं।

हालांकि, मैं हमेशा शीर्ष पर सुनना पसंद करता हूं और बस सभी डेटा नीचे पारित करता हूं। मैं कभी-कभी स्टोर की पूरी स्थिति भी ले सकता हूं और इसे एक वस्तु के रूप में पदानुक्रम के माध्यम से नीचे पारित कर सकता हूं, और मैं इसे कई स्टोरों के लिए करूंगा। तो मैं एक ArticleStoreराज्य के लिए एक प्रस्ताव होगा , और एक और UserStoreराज्य के लिए, आदि। मुझे लगता है कि गहरी नेस्टेड नियंत्रक-विचारों से बचने के लिए डेटा के लिए एक विलक्षण प्रवेश बिंदु बनाए रखता है, और डेटा प्रवाह को एकजुट करता है। अन्यथा, मेरे पास डेटा के कई स्रोत हैं, और यह डीबग करना मुश्किल हो सकता है।

इस रणनीति के साथ टाइप चेकिंग अधिक कठिन है, लेकिन आप रिएक्ट के प्रोपटीपेस के साथ बड़े ऑब्जेक्ट-ए-प्रॉप के लिए एक "आकृति", या प्रकार टेम्पलेट सेट कर सकते हैं। देखें: https://github.com/facebook/react/blob/master/src/core/ReactPropTypes.js#L76-L91 http://facebook.github.io/react/docs-reusable-compenders.html#prop -validation

ध्यान दें कि आप स्टोर में स्टोर के बीच डेटा को जोड़ने का तर्क स्वयं देना चाहते हैं। तो आपका ArticleStoreहो सकता waitFor()है UserStore, और Articleइसके द्वारा प्रदान किए गए प्रत्येक रिकॉर्ड के साथ प्रासंगिक उपयोगकर्ता शामिल करें getArticles()। अपने विचारों में ऐसा करने से तर्क परत में धकेलने जैसा लगता है, जो एक अभ्यास है जिसे आपको जब भी संभव हो बचना चाहिए।

आपको उपयोग करने के लिए भी लुभाया जा सकता है transferPropsTo(), और बहुत से लोग ऐसा करना पसंद करते हैं, लेकिन मैं पठनीयता और इस प्रकार स्थिरता के लिए सब कुछ स्पष्ट रखना पसंद करता हूं।

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


4
विस्तृत उत्तर के लिए धन्यवाद! मैंने स्टोर स्टेट के पूरे स्नैपशॉट को पारित करने पर विचार किया। हालाँकि, यह मुझे एक संपूर्ण समस्या दे सकता है क्योंकि UserStore के प्रत्येक अपडेट के कारण स्क्रीन पर सभी लेख पुनः प्रस्तुत हो जाएंगे, और PureRenderMixin यह नहीं बता पाएगा कि किन लेखों को अपडेट करने की आवश्यकता है, और जो नहीं करते हैं। आपके दूसरे सुझाव के अनुसार, मैंने इसके बारे में भी सोचा, लेकिन मैं यह नहीं देख सकता कि यदि लेख के उपयोगकर्ता को प्रत्येक getArticles () कॉल पर "इंजेक्ट" किया जाए तो मैं लेख संदर्भ समानता कैसे रख सकता हूं। यह फिर से संभावित रूप से मुझे संपूर्ण समस्याएं देगा।
दान अब्रामोव

1
मैं आपकी बात देखता हूं, लेकिन समाधान हैं। एक के लिए, यदि आप एक लेख के लिए उपयोगकर्ता आईडी का एक सरणी बदल गया है, जो मूल रूप से सिर्फ इस विशेष मामले में PureRenderMixin में वास्तव में आप चाहते हैं कार्यक्षमता और व्यवहार रोलिंग है, अगर आप canComponentUpdate () में देख सकते हैं।
फिशरदेबदेव

3
ठीक है, और वैसे भी मैं केवल यह सब करने की ज़रूरत है जब मैं कुछ वहाँ हूँ जाएगा रहे हैं पर्फ़ समस्याओं जो दुकानों के लिए मामला है कि प्रति मिनट अद्यतन कई बार अधिकतम नहीं होना चाहिए। फिर से धन्यवाद!
दान अब्रामोव

8
आप किस प्रकार के एप्लिकेशन का निर्माण कर रहे हैं, इस पर निर्भर करते हुए कि एक सिंगल एंट्री पॉइंट रखने से आपको जल्द ही स्क्रीन पर अधिक "विजेट्स" होने लगेंगे, जो सीधे उसी रूट से संबंधित नहीं हैं। यदि आप बलपूर्वक उस तरह से करने की कोशिश करते हैं, तो उस रूट नोड में बहुत अधिक जिम्मेदारी होगी। चुंबन और ठोस, यहां तक कि यह ग्राहक के पक्ष हालांकि।
रयगु सिप

37

जिस दृष्टिकोण से मैं पहुंचा था, प्रत्येक घटक को एक प्रोप के रूप में अपना डेटा (आईडी नहीं) प्राप्त होता है। यदि कुछ नेस्टेड घटक को संबंधित इकाई की आवश्यकता है, तो इसे पुनः प्राप्त करने के लिए मूल घटक पर निर्भर है।

हमारे उदाहरण में, Articleएक articleप्रोप होना चाहिए जो एक वस्तु है (संभवतः द्वारा ArticleListया फिर से प्राप्त ArticlePage)।

क्योंकि Articleयह भी प्रस्तुत करना चाहता है UserLinkऔर UserAvatarलेख के लेखक के लिए, यह अपने राज्य में सदस्यता UserStoreऔर रखेगा author: UserStore.get(article.authorId)। यह तो प्रस्तुत करना होगा UserLinkऔर UserAvatarइस के साथ this.state.author। यदि वे इसे और नीचे पारित करना चाहते हैं, तो वे कर सकते हैं। किसी भी बाल घटक को इस उपयोगकर्ता को फिर से प्राप्त करने की आवश्यकता नहीं होगी।

दोहराना:

  • कोई घटक कभी भी एक प्रस्ताव के रूप में आईडी प्राप्त नहीं करता है; सभी घटक अपनी-अपनी वस्तुओं को प्राप्त करते हैं।
  • यदि बच्चे के घटकों को एक इकाई की आवश्यकता होती है, तो इसे पुनः प्राप्त करना और एक प्रस्ताव के रूप में पारित करना माता-पिता की जिम्मेदारी है।

यह मेरी समस्या को काफी अच्छी तरह से हल करता है। इस दृष्टिकोण का उपयोग करने के लिए कोड उदाहरण फिर से लिखा गया:

var Article = React.createClass({
  mixins: [createStoreMixin(UserStore)],

  propTypes: {
    article: PropTypes.object.isRequired
  },

  getStateFromStores() {
    return {
      author: UserStore.get(this.props.article.authorId);
    }
  },

  render() {
    var article = this.props.article,
        author = this.state.author;

    return (
      <div>
        <UserLink user={author}>
          <UserAvatar user={author} />
        </UserLink>

        <h1>{article.title}</h1>
        <p>{article.text}</p>

        <p>Read more by <UserLink user={author} />.</p>
      </div>
    )
  }
});

var UserAvatar = React.createClass({
  propTypes: {
    user: PropTypes.object.isRequired
  },

  render() {
    var user = this.props.user;

    return (
      <img src={user.thumbnailUrl} />
    )
  }
});

var UserLink = React.createClass({
  propTypes: {
    user: PropTypes.object.isRequired
  },

  render() {
    var user = this.props.user;

    return (
      <Link to='user' params={{ userId: this.props.user.id }}>
        {this.props.children || user.name}
      </Link>
    )
  }
});

यह अंतरतम घटकों को बेवकूफ बनाए रखता है, लेकिन हमें शीर्ष स्तर के घटकों से नरक को जटिल करने के लिए मजबूर नहीं करता है।


बस इस उत्तर के शीर्ष पर एक परिप्रेक्ष्य जोड़ना है। वैचारिक रूप से, आप स्वामित्व की धारणा विकसित कर सकते हैं, यह देखते हुए कि एक डेटा संग्रह शीर्ष पर सबसे अधिक दृश्य को अंतिम रूप देता है जो वास्तव में डेटा का मालिक है (इसलिए इसकी दुकान को सुन रहा है)। कुछ उदाहरण: 1. AuthData को एप कंपोनेंट पर स्वामित्व होना चाहिए। Auth में किसी भी बदलाव को एप कंपोनेंट द्वारा सभी चिल्ड प्रॉप्स के रूप में प्रचारित किया जाना चाहिए। 2. ArticleData का जवाब में ArticlePage या Article सूची के रूप में स्वामित्व होना चाहिए। अब ArticleList का कोई भी बच्चा ArticleDist से AuthData और / या ArticleData प्राप्त कर सकता है, इस बात की परवाह किए बिना कि किस घटक ने वास्तव में उस डेटा को प्राप्त किया है।
सौमित्र आर। भावे

2

मेरा समाधान बहुत सरल है। प्रत्येक घटक की अपनी स्थिति होती है जिसे स्टोरों से बात करने और सुनने की अनुमति दी जाती है। ये बहुत नियंत्रक-जैसे घटक हैं। डीप नेस्टेड घटक जो राज्य को बनाए नहीं रखते हैं, लेकिन केवल सामान सौंपने की अनुमति नहीं है। वे केवल शुद्ध प्रतिपादन के लिए प्रॉप्स प्राप्त करते हैं, बहुत दृश्य-जैसे।

इस तरह सब कुछ स्टेटफुल कंपोनेंट से स्टेटलेस कंपोनेंट में बहता है। स्टेटफुल की गिनती कम रखते हैं।

आपके मामले में, अनुच्छेद स्टेटफुल होगा और इसलिए स्टोर और यूजरलिंक इत्यादि से बातचीत केवल प्रस्तुत करना होगा, ताकि उसे अनुच्छेद.सुख प्राप्त हो।


1
मुझे लगता है कि यह काम करेगा अगर लेख में उपयोगकर्ता ऑब्जेक्ट संपत्ति थी, लेकिन मेरे मामले में यह केवल userId है (क्योंकि वास्तविक उपयोगकर्ता UserStore में संग्रहीत है)। या मुझे आपकी बात याद आ रही है? क्या आप एक उदाहरण साझा करेंगे?
दान अब्रामोव

लेख में उपयोगकर्ता के लिए एक भ्रूण आरंभ करें। या उपयोगकर्ता आईडी को "विस्तार योग्य" बनाने के लिए अपने एपीआई बैकएंड को बदलें ताकि आप उपयोगकर्ता को एक ही बार में प्राप्त कर सकें। किसी भी तरह से गहरी नेस्टेड घटकों को सरल विचार और केवल सहारा पर निर्भर रखें।
रयगु सेप Ry

2
मैं लेख को लाने की पहल नहीं कर सकता क्योंकि इसे एक साथ प्रस्तुत करने की आवश्यकता है। विस्तार योग्य एपीआई के लिए, हमारे पास उनका उपयोग होता था, लेकिन वे स्टोर से पार्स करने के लिए बहुत समस्याग्रस्त हैं। मैंने इस कारण से प्रतिक्रियाओं को समतल करने के लिए एक पुस्तकालय भी लिखा था ।
दान अब्रामोव

0

आपके 2 दर्शनों में वर्णित समस्याएं किसी एक पृष्ठ के आवेदन के लिए सामान्य हैं।

इस वीडियो में उनकी संक्षिप्त चर्चा की गई है: https://www.youtube.com/watch?v=IrgHurBjQbg और Relay ( https://facebook.github.io/relay ) को आपके द्वारा वर्णित ट्रेडऑफ़ को दूर करने के लिए फेसबुक द्वारा विकसित किया गया था।

रिले का दृष्टिकोण बहुत डेटा केंद्रित है। यह इस सवाल का जवाब है कि "इस दृश्य में प्रत्येक घटक के लिए सर्वर के लिए एक क्वेरी में मुझे केवल आवश्यक डेटा कैसे मिलेगा?" और एक ही समय में रिले सुनिश्चित करता है कि आपके पास कोड में बहुत कम युग्मन है जब एक घटक कई दृश्यों में उपयोग किया जाता है।

यदि रिले एक विकल्प नहीं है , तो "सभी इकाई घटक अपने स्वयं के डेटा को पढ़ते हैं" मुझे आपके द्वारा वर्णित स्थिति के लिए एक बेहतर दृष्टिकोण लगता है। मुझे लगता है कि फ्लक्स में गलत धारणा एक स्टोर है। स्टोर की अवधारणा का कोई स्थान नहीं है जहां एक मॉडल या वस्तुओं का संग्रह रखा जाता है। स्टोर अस्थायी स्थान होते हैं जहां आपके एप्लिकेशन को दृश्य प्रदान करने से पहले डेटा डाल दिया जाता है। उनके पास मौजूद वास्तविक कारण विभिन्न स्टोरों में जाने वाले डेटा पर निर्भरता की समस्या को हल करना है।

फ्लक्स निर्दिष्ट नहीं कर रहा है कि एक दुकान मॉडल की अवधारणा और वस्तुओं के संग्रह (एक ला बैकबोन) से कैसे संबंधित है। इस अर्थ में, कुछ लोग वास्तव में एक फ्लक्स स्टोर को एक ऐसी जगह बना रहे हैं जहां एक विशिष्ट प्रकार की वस्तुओं का संग्रह करना है जो कि पूरे समय के लिए फ्लश नहीं है उपयोगकर्ता ब्राउज़र को खुला रखता है लेकिन, जैसा कि मैं फ्लक्स को समझता हूं, वह स्टोर नहीं है ऐसा माना जाता है।

समाधान के लिए एक और परत होती है, जहां आप अपने दृष्टिकोण (और संभवतः अधिक) को प्रस्तुत करने के लिए आवश्यक इकाइयां संग्रहीत और अद्यतन रखी जाती हैं। यदि आप इस परत को अमूर्त मॉडल और संग्रह करते हैं, तो यह समस्या नहीं है यदि आपको अपने डेटा प्राप्त करने के लिए सब-कमर्स को फिर से क्वेरी करनी है।


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