फ़ेसबुक रिएक्ट में कोड पुन: उपयोग के लिए मिश्रित बनाम घटकों का उपयोग करना


116

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

उदाहरण के लिए, मेरे पास कई फ़ॉर्म-जैसे विजेट हैं जैसे राज्यों के साथ INITIAL, SENDINGऔर SENT। जब एक बटन दबाया जाता है, तो फॉर्म को मान्य करने की आवश्यकता होती है, एक अनुरोध किया जाता है, और फिर स्थिति अपडेट की जाती है। this.stateक्षेत्र के मूल्यों के साथ, राज्य को प्रतिक्रिया के अंदर रखा जाता है ।

अगर ये बैकबोन विचार थे, तो मुझे एक बेस क्लास कहा जाता था, FormViewलेकिन मेरी धारणा थी कि रिएक्ट न तो एंडोर्स करता है और न ही सब लॉजिक को सपोर्ट करता है ताकि व्यू लॉजिक को शेयर किया जा सके (मुझे गलत लगे तो सही करें)।

मैंने रिएक्ट में कोड पुन: उपयोग के लिए दो दृष्टिकोण देखे हैं:

क्या मैं सही हूं कि मिक्स और कंटेनर रिएक्ट में विरासत के लिए पसंद किए जाते हैं? क्या यह जानबूझकर किया गया निर्णय है? क्या यह दूसरे पैराग्राफ से मेरे "फ़ॉर्म विजेट" उदाहरण के लिए मिक्सिन या कंटेनर घटक का उपयोग करने के लिए अधिक समझदार होगा?

यहाँ FeedbackWidgetऔर JoinWidgetउनके वर्तमान स्थिति में एक जिस्ट है । उनके पास एक समान संरचना, समान beginSendविधि है और दोनों को कुछ सत्यापन समर्थन (अभी तक नहीं) की आवश्यकता होगी।


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

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

मिश्रण कभी नहीं मरेंगे क्योंकि आप हमेशा DIY मिश्रण बना सकते हैं। रिएक्ट में सिर्फ मिक्सिन्स के लिए "देशी" समर्थन नहीं होगा, लेकिन आप अभी भी देशी जेएस के साथ मिक्सिंस खुद कर सकते हैं।
अलेक्जेंडर मिल्स

जवाबों:


109

अद्यतन: यह उत्तर पुराना है। यदि आप कर सकते हैं तो मिश्रण से दूर रहें। मैंने तुम्हे चेतावनी दी थी। मैंने तुम्हे चेताया था!
मिक्सिंस डेड। लंबे समय तक जीवित रचना

सबसे पहले, मैंने इसके लिए सब-पार्टनर्स का उपयोग करने की कोशिश की और निकालने FormWidgetऔर InputWidget। हालाँकि, मैंने इस दृष्टिकोण को आधा छोड़ दिया क्योंकि मैं उत्पन्न inputs और उनके राज्य पर बेहतर नियंत्रण चाहता था ।

दो लेख जिनसे मुझे सबसे ज्यादा मदद मिली:

यह पता चला कि मुझे केवल दो (अलग) मिश्रण लिखने की जरूरत थी: ValidationMixinऔर FormMixin
यहां बताया गया है कि मैंने उन्हें कैसे अलग किया।

ValidationMixin

सत्यापन मिश्रण अपने राज्य के कुछ गुणों पर अपने सत्यापनकर्ता कार्यों को चलाने के लिए सुविधा विधियों को जोड़ता है और state.errorsसरणी में "त्रुटि" गुणों को संग्रहीत करता है ताकि आप संबंधित क्षेत्रों को उजागर कर सकें।

स्रोत ( जिस्ट )

define(function () {

  'use strict';

  var _ = require('underscore');

  var ValidationMixin = {
    getInitialState: function () {
      return {
        errors: []
      };
    },

    componentWillMount: function () {
      this.assertValidatorsDefined();
    },

    assertValidatorsDefined: function () {
      if (!this.validators) {
        throw new Error('ValidatorMixin requires this.validators to be defined on the component.');
      }

      _.each(_.keys(this.validators), function (key) {
        var validator = this.validators[key];

        if (!_.has(this.state, key)) {
          throw new Error('Key "' + key + '" is defined in this.validators but not present in initial state.');
        }

        if (!_.isFunction(validator)) {
          throw new Error('Validator for key "' + key + '" is not a function.');
        }
      }, this);
    },

    hasError: function (key) {
      return _.contains(this.state.errors, key);
    },

    resetError: function (key) {
      this.setState({
        'errors': _.without(this.state.errors, key)
      });
    },

    validate: function () {
      var errors = _.filter(_.keys(this.validators), function (key) {
        var validator = this.validators[key],
            value = this.state[key];

        return !validator(value);
      }, this);

      this.setState({
        'errors': errors
      });

      return _.isEmpty(errors);
    }
  };

  return ValidationMixin;

});

प्रयोग

ValidationMixinतीन तरीकों है: validate, hasErrorऔर resetError
यह वर्ग को validatorsवस्तु के समान परिभाषित करने की उम्मीद करता है propTypes:

var JoinWidget = React.createClass({
  mixins: [React.addons.LinkedStateMixin, ValidationMixin, FormMixin],

  validators: {
    email: Misc.isValidEmail,
    name: function (name) {
      return name.length > 0;
    }
  },

  // ...

});

जब उपयोगकर्ता सबमिट बटन दबाता है, तो मैं कॉल करता हूं validate। कॉल validateप्रत्येक सत्यापनकर्ता को चलाएगी और this.state.errorsउस सरणी के साथ पॉप्युलेट होगी जिसमें सत्यापन विफल होने वाले गुणों की कुंजी है।

अपनी renderपद्धति में, मैं hasErrorखेतों के लिए सही CSS क्लास उत्पन्न करने के लिए उपयोग करता हूं । जब उपयोगकर्ता क्षेत्र के अंदर ध्यान केंद्रित करता है, तो मैं resetErrorअगले validateकॉल तक त्रुटि हाइलाइट को दूर करने के लिए कहता हूं ।

renderInput: function (key, options) {
  var classSet = {
    'Form-control': true,
    'Form-control--error': this.hasError(key)
  };

  return (
    <input key={key}
           type={options.type}
           placeholder={options.placeholder}
           className={React.addons.classSet(classSet)}
           valueLink={this.linkState(key)}
           onFocus={_.partial(this.resetError, key)} />
  );
}

FormMixin

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

स्रोत ( जिस्ट )

define(function () {

  'use strict';

  var _ = require('underscore');

  var EDITABLE_STATE = 'editable',
      SUBMITTING_STATE = 'submitting',
      SUBMITTED_STATE = 'submitted';

  var FormMixin = {
    getInitialState: function () {
      return {
        formState: EDITABLE_STATE
      };
    },

    componentDidMount: function () {
      if (!_.isFunction(this.sendRequest)) {
        throw new Error('To use FormMixin, you must implement sendRequest.');
      }
    },

    getFormState: function () {
      return this.state.formState;
    },

    setFormState: function (formState) {
      this.setState({
        formState: formState
      });
    },

    getFormError: function () {
      return this.state.formError;
    },

    setFormError: function (formError) {
      this.setState({
        formError: formError
      });
    },

    isFormEditable: function () {
      return this.getFormState() === EDITABLE_STATE;
    },

    isFormSubmitting: function () {
      return this.getFormState() === SUBMITTING_STATE;
    },

    isFormSubmitted: function () {
      return this.getFormState() === SUBMITTED_STATE;
    },

    submitForm: function () {
      if (!this.isFormEditable()) {
        throw new Error('Form can only be submitted when in editable state.');
      }

      this.setFormState(SUBMITTING_STATE);
      this.setFormError(undefined);

      this.sendRequest()
        .bind(this)
        .then(function () {
          this.setFormState(SUBMITTED_STATE);
        })
        .catch(function (err) {
          this.setFormState(EDITABLE_STATE);
          this.setFormError(err);
        })
        .done();
    }
  };

  return FormMixin;

});

प्रयोग

यह घटक को एक विधि प्रदान करने की उम्मीद करता है: sendRequestजिसे ब्लूबर्ड वादा वापस करना चाहिए। (यह क्यू या अन्य वादा पुस्तकालय के साथ काम करने के लिए इसे संशोधित करने के लिए तुच्छ है।)

यह इस तरह के रूप में सुविधा के तरीके प्रदान करता है isFormEditable, isFormSubmittingऔर isFormSubmitted। यह अनुरोध को बंद करने के लिए एक विधि भी प्रदान करता है submitForm:। आप इसे फॉर्म बटन के onClickहैंडलर से कह सकते हैं ।


2
@jmcejuela वास्तव में मैं बाद में और अधिक घटक-ईश दृष्टिकोण पर आ गया (अभी भी मिक्सी का भारी उपयोग कर रहा हूं), मैं कुछ बिंदु पर इस पर विस्तार कर सकता हूं ..
दान अब्रामोव

1
क्या "अधिक घटक-ईश दृष्टिकोण" के बारे में कुछ समाचार है?
निलकोल

3
@ नीलचोर अभी नहीं, मैं इससे काफी संतुष्ट नहीं हूं। :-) वर्तमान में मेरे पास FormInputइसके मालिक से बातचीत है formLinkformLinkकी तरह है valueLink, और से दिया जाता है FormMixinकी linkValidatedState(name, validator)विधि। FormInputसे अपने मूल्य हो जाता है formLink.valueऔर कॉल formLink.requestBlurऔर formLink.requestFocusमें, वे कारण मान्यता FormMixin। अंत में, इनपुट के लिए उपयोग किए जा रहे वास्तविक घटक को अनुकूलित करने के लिए, मैं इसे पास कर सकता हूं FormInput:<FormInput component={React.DOM.textarea} ... />
दान Abramov

अच्छा जवाब - कुछ टिप्स: आपको doneब्लूबर्ड में कॉल करने की आवश्यकता नहीं है और क्यू के रूप में कोड (या मूल वादों) में काम करेगा - बेशक ब्लूबर्ड बेहतर है। यह भी ध्यान दें कि जवाब के बाद से सिंटैक्स रिएक्ट में बदल गया।
बेंजामिन ग्रुएनबाम

4

मैं एक एसपीए का निर्माण कर रहा हूं जिसमें रिएक्ट (1 वर्ष से उत्पादन में) है, और मैं लगभग कभी भी मिश्रण का उपयोग नहीं करता हूं।

केवल वर्तमान में मेरे पास मिक्सी के लिए उपयोग किया जाता है, जब आप व्यवहार को साझा करना चाहते हैं जो रिएक्ट के जीवनचक्र विधियों ( componentDidMountआदि) का उपयोग करता है । यह समस्या हायर-ऑर्डर कंपोनेंट्स द्वारा हल की गई है जो डैन अब्रामोव अपने लिंक में बात करते हैं (या ईएस 6 क्लास इनहेरिटेंस का उपयोग करके)।

मिक्सिंस का उपयोग अक्सर फ्रेमवर्क एपीआई में भी किया जाता है, ताकि रिएक्ट की "छिपी" संदर्भ सुविधा का उपयोग करके सभी घटकों को फ्रेमवर्क एपीआई उपलब्ध हो सके । यह अब ES6 वर्ग विरासत के साथ भी जरूरत नहीं होगी।


अधिकांश समय में, मिश्रण का उपयोग किया जाता है, लेकिन वास्तव में इसकी आवश्यकता नहीं होती है और सरल सहायकों के साथ आसानी से प्रतिस्थापित किया जा सकता है।

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

var WithLink = React.createClass({
  mixins: [React.addons.LinkedStateMixin],
  getInitialState: function() {
    return {message: 'Hello!'};
  },
  render: function() {
    return <input type="text" valueLink={this.linkState('message')} />;
  }
});

आप बहुत आसानी से LinkedStateMixinकोड को रिफ्लेक्टर कर सकते हैं ताकि वाक्यविन्यास हो जाए:

var WithLink = React.createClass({
  getInitialState: function() {
    return {message: 'Hello!'};
  },
  render: function() {
    return <input type="text" valueLink={LinkState(this,'message')} />;
  }
});

क्या कोई बड़ा अंतर है?


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