React: الدعائم الافتراضية في بنية فئة ES6

تم إنشاؤها على ٢٢ أبريل ٢٠١٥  ·  40تعليقات  ·  مصدر: facebook/react

يقول إعلان دعم ES6 :

الطريقة الاصطلاحية لتحديد حالة الفئة هي مجرد استخدام خاصية مثيل بسيطة. وبالمثل ، فإن getDefaultProps و propTypes هي في الحقيقة مجرد خصائص على المُنشئ.

هذا منطقي جدًا بالنسبة لي ، لكنني لاحظت بعض التناقضات الصغيرة التي قد تستحق إعادة التفكير.

عند استخدام بناء الجملة الأصلي .createClass ، يبدو أن القيمة التي تم إرجاعها بواسطة getDefaultProps مستخدمة في نقاط أخرى في دورة حياة المكون - وليس فقط في المنشئ. على سبيل المثال ، إذا قمت بفحص ما يتم إرساله إلى componentWillReceiveProps(props) ، يمكنني ملاحظة أنه تم تطبيق الخاصيات الافتراضية.

لا يبدو أن هذا هو الحال عند استخدام بناء جملة فئة ES6 ، مما يعني أنه يتعين علي تكرار التعليمات البرمجية. هذا مثال على ما أعنيه:

class Control extends React.Component {

  constructor(props) {
    props.value = props.value || '';
    super(props);
  }

  // ...

  componentWillReceiveProps(props) {
    props.value = props.value || '';
    // Do something with props...
  }

}

كما ترى ، أقوم بتكرار التعبير props.value = props.value || '' . إذا كان لدي أكثر من افتراضي واحد ، فمن الواضح أن لدي الكثير من الازدواجية.

عند استخدام طريقة .createClass ، يمكنني إرجاع {value: ''} من طريقة getDefaultProps ، وسينجح هذا الأمر ، وسأضطر إلى القيام بذلك مرة واحدة فقط.

هل يعقل استعادة هذه الطريقة لتجنب الازدواجية غير الضرورية؟ هل هناك نهج آخر يشبه التفاعل لست على دراية به؟

التعليق الأكثر فائدة

هذا صحيح. بدلاً من ذلك ، تكتب هذا:

class Control extends React.Component {

  // ...

  componentWillReceiveProps(props) {
    // Do something with props...
  }

}
Control.defaultProps = {value: ''};

هل هذا مناسب لك؟

ال 40 كومينتر

يجب أن تكون الخاصيات الافتراضية مدمجة بالفعل عند استدعاء componentWillReceiveProps.

يجب أن تكون الخاصيات الافتراضية مدمجة بالفعل عند استدعاء componentWillReceiveProps.

بقدر ما أستطيع أن أقول ، لا يتم استدعاء getDefaultProps أبدًا عند استخدام بناء جملة فئة ES6.

هذا صحيح. بدلاً من ذلك ، تكتب هذا:

class Control extends React.Component {

  // ...

  componentWillReceiveProps(props) {
    // Do something with props...
  }

}
Control.defaultProps = {value: ''};

هل هذا مناسب لك؟

آه ، آسف ، أرى ذلك في الوثائق الآن. شكرا!

نظرًا لأنني وصلت إلى هنا من بحث Google ، وأفضّل class لتغليف الكود الخاص بي ، يمكن تعيين العناصر الافتراضية باستخدام خصائص محسوبة مثل:

import React, {Component, PropTypes} from 'react'
class DefaultPropsExample extends Component {
  static defaultProps = {
    ...Component.defaultProps,
    instructions: 'Usage instructions not provided.',
  }
}

jhabdas ما قدمته ليس صيغة ES2015 ، على ما أعتقد ؛ يقوم Babel بإلقاء رمز غير متوقع إذا استخدمت الدعائم الثابتة ، ومع ذلك ، بالنسبة لأولئك الرجال الذين يعملون مثلي في es2015 ، فهذه أشياء تعمل.

import React from 'react';
export default class extends React.Component {

  static get defaultProps() {
    return {
      // stuff you want :)
    }
  }

}

تحديث

بعد تثبيت رابطzpao ، يمكنني استخدام الخصائص الثابتة ...

@ Gopikrishna19 ، ستحتاج إلى تمكين ملحق babel آخر يقوم بتنفيذ خاصية خصائص الفئة: http://babeljs.io/docs/plugins/transform-class-properties/

تضمين التغريدة أشياء جديدة أخرى اليوم :) ستحاول ذلك ، شكرًا جزيلاً!

@ Gopikrishna19 لقد أحببت فعلاً مقتطف الشفرة الذي نشرته ب / ج يمكنني إجراء بعض المعالجة المسبقة قبل تهيئة الدعائم الافتراضية. شكرا لذكرها.

يبدو أن هذا يعمل وهو أكثر أناقة في رأيي:

....

 static defaultProps = {
      //someDefaultProps
  };

  constructor(props, defaultProps) {
    super(props, defaultProps);
  }

....

fxhereng الوسيطة الثانية محجوزة لـ context لذلك سأتجنب تجاوزها ببعض المعنى المخصص لأن هذا قد ينقطع في الإصدارات المستقبلية.

Okgaearon ما هي أفضل طريقة لتعيين الدعائم الافتراضية لك؟

شكرا،

ما هي الطريقة الموصى بها لذلك؟

إذا كنت تستخدم التحويل التجريبي http://babeljs.io/docs/plugins/transform-class-properties/ ، فيمكنك فقط استخدام static defaultProps = {...}; . لا حاجة لإجراء تغييرات على المنشئ. خلاف ذلك ، تحتاج إلى تعيين خارج:

class X extends React.Component {
}
X.defaultProps = {...};

أيضا..

class X extends React.Component {
  props = {
    ...
  }
}

efernandesng هذا ليس نمطًا مدعومًا. لن يتصرف مثل defaultProps وسيتغير this.props وهو ما لا يجب عليك فعله.

يبدو أنه لا يمكنني الحصول على العناصر الافتراضية ليتم إنشاء مثيل لها مع الفئة الأصلية حتى يمكنني تمرير هذه الدعائم إلى فئة فرعية أخرى بداخلها.

هل هناك طريقة es6 معيارية للقيام بذلك؟ جميع الطرق الموجودة هنا لا تعمل معي.

يبدو أنه لا يمكنني الحصول على العناصر الافتراضية ليتم إنشاء مثيل لها مع الفئة الأصلية حتى يمكنني تمرير هذه الدعائم إلى فئة فرعية أخرى بداخلها.

أنا لا أفهم ما تقصد. يمكنك إظهار مثال؟

بالطبع ، آسف لذلك.

هنا مكون:

import React, 
{
  Component,
  PropTypes
}                     from 'react';
import { TimerView }  from './TimerView'

class Timer extends Component {
  constructor(props) {
    super(props);
  }

  componentWillReceiveProps(props) {
    console.log('Will receive props')
  }

  render() {
    console.log("Timer loaded")

    return (
      <TimerView {...props} />
    )
  }
}

Timer.propTypes = {
  status: PropTypes.string.isRequired,
};

Timer.defaultProps = {
  status: "This is the Timer",
};

export default Timer;

عندما أقوم بتشغيل خادم webpack-dev-server ، أحصل على هذا الخطأ:
Uncaught ReferenceError: props is not defined

لابد أن هناك شيئًا خاطئًا أفعله ...

props متغير غير منضم في طريقة render() . يجب أن يكون <TimerView {...this.props} /> .

يا بلادي.
لقد فاتني هذا تماما. أعتقد بما أنني أستخدم مكونات عديمة الجنسية مثلها مثل الفصول الدراسية ، فقد شعرت بالارتباك حيال هذا العنصر.

شكرا لك سيدي.

لا مشكلة @ jeanmichelcote! يحدث :)

الوصول إلى الدعائم الأخرى لتعريف الافتراضي تعتبر الدعائم مضادًا للنمط؟

class Comp extends from React.Component {
  static propTypes: {
    num: React.PropTypes.number.isRequired,
    action: React.PropTypes.func,
  };

  static defaultProps: {
    action: () => console.log(this.props.num), // "this" is invalid in static context
  };

  render() {
    return (
      <button onClick={this.props.action}>
        {`Log #${this.props.num}`}
      </button>
    );
  }
}

romulof يبدو أنك تحاول الإشارة إلى متغير حالة من طريقة ثابتة. لا يمكنك القيام بذلك لأنه لا توجد طريقة لمعرفة this الذي تتحدث عنه. بحكم التعريف ، تعيش الأشياء الثابتة دائمًا خارج سياق مثيل.

romulof هذا شائع مع جميع اللغات الموجهة للكائنات. يرتبط بناء جملة السهم السميك بالسياق المحدد فيه. ربما يمكنك محاولة استخدامه

static defaultProps: {
    action: function() {
        console.log(this.props.num), // "this" depends on the context where it is run
    }
};

sbussard : بالضبط.

سؤالي حول تنفيذ defaultProps ككائن ثابت.
ربما السماح لها بأن تكون دالة ، ليتم استدعاؤها من قبل المنشئ.

إنه خارج الفصل عن قصد حتى يتمكن المحول البرمجي المحسن من تضمينه في موقع الاستدعاء.

إذن ما هو الجواب النهائي؟

gaearon لقد ذكرت ذلك

إنه خارج الفصل عن قصد حتى يتمكن المحول البرمجي المحسن من تضمينه في موقع الاستدعاء.

ولكن هل هذا يعني أنه لا يمكن تحسينها عند استخدام "حقول مثيل الفئة" و / أو "حقول فئة ثابتة"؟ أعتقد أنني أحاول فهم النهج المفضل ولماذا.

إذن ما هو الجواب النهائي؟

إذا كنت تريد التمسك بـ ES6 ، فقم بتعيينه في الأسفل:

class MyComponent extends Component { /* ... */ }
MyComponent.defaultProps = { /* ... */ };

إذا كنت تستخدم تطبيق Create React ، أو إذا كنت مرتاحًا للصياغة التجريبية وقمت بتمكين تحويل خصائص الفئة ، فيمكنك القيام بذلك:

class MyComponent extends Component {
  static defaultProps = { /* ... */ };
  /* ... */
}

هذه الأساليب متكافئة تمامًا. لاحظ أنه إذا كنت تستخدم أدوات تزيين أيضًا ، فقد يكون لديك أخطاء غريبة تجمع بين هذه التحولات. لذلك لا أوصي باستخدام الزخرفة مع خصائص الفصل.

آمل أن يساعد هذا!

ولكن هل هذا يعني أنه لا يمكن تحسينها عند استخدام "حقول مثيل الفئة" و / أو "حقول فئة ثابتة"؟ أعتقد أنني أحاول فهم النهج المفضل ولماذا.

لا يوجد فرق بين التعيين في النهاية واستخدام خصائص الفئة. فئة الخصائص desugar للتخصيص. يرجى استخدام REPL على موقع Babel للتحقق من الكود الذي يتم التحويل إليه.

لدي فضول حول نفس المشكلة التي يتحدث عنها romulof . بالتأكيد ، يمكنني استخدام static defaultProps لتعريف الخصائص الافتراضية ولكن ماذا لو أردت استخدام السياق؟

لماذا هذا مفيد؟

لدي مكون شكلي عام يحتوي على عناصر title و onSubmit . أحيانًا أرغب في استخدام Modal بنفس الدعائم ولكن من أجزاء مختلفة تمامًا من تطبيقي. مقابل title هذا يعمل بشكل جيد.

class CreateUserModal extends Modal {
  static defaultProps = { title: 'Create a new user' }
}

ومع ذلك ، فإن المعالج onSubmit ، والذي يُصادف أنه جزء لائق من التعليمات البرمجية ، يتطلب سياق لأنه يستخدم دعامة مملوءة من إعادة الاتصال. لا توجد طريقة حاليًا لتلخيص هذا الرمز لأنه لا يمكن استخدام السياق لتعيين الدعائم الخاصة بالفئة الأصلية.

ما أحاول القيام به ليس في الحقيقة نمطًا مضادًا (أو على الأقل أعتقد أنه ليس كذلك) لذا أتساءل عما إذا كانت هناك طريقة أخرى للقيام بذلك؟

كنت آمل أن أتمكن من القيام بشيء مثل

class CreateUserModal extends Modal {
  constructor (props) {
    super({
      title: 'Create a new user',
      onSubmit: () => {
        // do a load of stuff using props
      }
    })
  }
}

لكنها لا تعمل.

roberttod هل وجدت حلاً لمشكلتك؟ شكرا

أريد أن أطرح سؤال متابعة ،
إذا كنت أستخدم إنشاء تطبيق تفاعل (نصوص تفاعلية v1.0.12) ، فهل من المقبول تحديد الحالات الأولية كـ

class Foo extends Component {
  static defaultProps = {};

  static propTypes = {};

  state = {...};
}

ما هو الفرق مقارنة باستخدام المنشئات لتحديد الحالات الأولية على النحو التالي:

class Foo extends Component {
  static defaultProps = {};

  static propTypes = {};

  constructor(props) {
    super(props);

    this.state = {...};
  }
}

على وجه التحديد ، هل هناك أي آثار على الأداء في النهج الأول؟

إنه نفس الشيء بالضبط ، لا فرق.

jhabdas حسنًا ، لذلك عندما يتم تعريف الافتراضي الدعوات على النحو التالي:

static defaultProps = {
}

كيفية الوصول إليه من طرق الفصل منذ:

this.defaultProps

إرجاع undefined

majioa لا أعرف عن واجهة برمجة التطبيقات على مستوى الفصل ، ولكن إحدى الأفكار هي تخزين الدعائم الافتراضية مؤقتًا ككائن منفصل والإشارة إلى ذلك. ماذا تعتقد؟

تضمين التغريدة

class Foo extends React.Component {
  static defaultProps = { param: 1 };
  render() {
    return Foo.defaultProps.param;
  }
}

أواجه نفس المشكلة ، يجب عليك تثبيت خصائص babel-plugin-transform-class-class

npm install -D babel-plugin-transform-class-properties

ثم أضف "transform-class-properties" إلى .babelrc

{
  "presets": ["env", "react"],
  "plugins": ["react-hot-loader/babel", "transform-class-properties"]
}

static get defaultProps () {
إرجاع {
السيارة: "مرسيدس"
}

@ Arm7107 هذا غير فعال لأنه يقوم بإنشاء كائن جديد في كل مرة يتم فيها إنشاء عنصر. أنصح بشدة بعدم استخدام هذا. إما أن تقوم بتعيين خاصية:

MyComponent.defaultProps = {
  // ...
}

أو استخدم بناء جملة خصائص فئة ثابتة تجريبية :

class MyComponent extends React.Component {
  static defaultProps = {
    // ...
  };

  // ...
}

(التي ستحتاج إلى مكون Babel الإضافي من أجلها)

سوف أقفل هذه المشكلة لمنع المزيد من الاقتراحات غير الصحيحة التي ستظهر في نتائج Google.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات