الشروع في العمل مع مكتبة جافا سكريبت React

نشرت: 2022-02-16

إذا كنت تقضي أي وقت في عالم WordPress ، فمن المحتمل أنك صادفت Zac Gordon. Zac هو مدرس متحمس وساحر يركز على Javascript في WordPress. استعار عبارة "Learn Javascript Deeply" من Matt Mullenweg وجعلها شعاره الشخصي.

على مدى السنوات العديدة الماضية ، أنتج Zac دروسًا بالفيديو ومؤتمرات عبر الإنترنت ومحادثات مباشرة وبودكاست تركز على تعليمك كيفية استخدام Javascript في WordPress.

يسعدني أن أقول إننا نعمل مع زاك على كتاب "شرح رد الفعل". React هي المكتبة التي اختارها فريق WordPress لمحرر Gutenberg الجديد. إنهم ليسوا وحدهم - فقد اختار كل من دروبال وماجينتو أيضًا React.

يقوم زاك بالتغريد المباشر لما أحرزه من تقدم في الكتابة علىzgordon على Twitter. يمكنك أيضًا سماع Zac يتحدث عن React على بودكاست OSTraining.

في هذا المقتطف من الكتاب ، يمنحك Zac نظرة عامة عالية المستوى حول React وبعض المفاهيم الأساسية.


ما هي React؟

من خارج الصندوق ، تعتبر React مكتبة لبناء واجهات المستخدم.

على الرغم من أن React عبارة عن مكتبة JavaScript ، إلا أن الواجهات التي يبنيها React حيادية.

توجد العديد من مكتبات React المصاحبة من أجل جعل الواجهات التي تقوم بإنشائها تعمل في المتصفح وعلى الخادم وفي التطبيقات الأصلية وحتى في بيئات 360 و VR. في هذا الكتاب ، نركز على العمل مع ReactDOM ، المكتبة التي تدير إضافة الواجهات التي نبنيها باستخدام React إلى مواقع الويب والتطبيقات من جانب العميل. ReactDomServer و ReactNative و React360 هي أيضًا مكتبات قد ترغب في استكشافها لاستخدام واجهات React في بيئات أخرى.

بالإضافة إلى توفير وظائف مساعدة لبناء الواجهات ، تسمح لك بنية React بالتعامل مع التفاعلات مع واجهاتك ، سواء كان ذلك يتضمن معالجة الأحداث ، أو مكالمات api ، أو إدارة الحالة ، أو تحديثات الواجهة ، أو تفاعلات أكثر تعقيدًا.

لا توفر React العديد من الوظائف المساعدة مثل بعض أطر عمل JavaScript. هذا إلى حد كبير سبب تسمية React مكتبة وليس إطار عمل. ستظل بحاجة إلى كتابة الكثير من JavaScript الفانيليا عند العمل مع React.


شرح هندسة مكونات التفاعل

المكون هو جزء مستقل من التعليمات البرمجية يمكن إعادة استخدامه (يتم إنشاؤه عبر وظيفة أو فئة).

تستخدم React بنية مكونة لبناء واجهات مستخدم وتنظيم التعليمات البرمجية. قد يبدو الملف الرئيسي لتطبيق React بسيط مثل هذا.

 // استيراد React والمكونات الأخرى
استيراد رد من "رد فعل" ؛
استيراد {عرض} من "رد فعل دوم" ؛
استيراد رأس من "./Header" ؛
استيراد MainContent من "./MainContent" ؛
استيراد تذييل من "./Footer" ؛

وظيفة التطبيق () {
  إرجاع (
    <div className = "app">
      <رأس />
      <MainContent />
      <تذييل />
    </div>
 ) ؛
}

ReactDOM.render (<App />، document.getElementById ("root")) ؛

يمكننا أن نرى هنا بعض المكونات قيد الاستخدام. <Header /> و <MainContent /> و <التذييل /> كلها مكونات. تعد وظيفة App () مكونًا أيضًا ويمكننا أن نرى في السطر الأخير من هذا المثال كيف يمكننا استخدام مكتبة ReactDOM وطريقة ReactDOM.render () لإدارة إضافة واجهة المستخدم التي نبنيها إلى صفحة ويب.

إذا بحثنا داخل مكونات <Header /> و <MainContent /> و <Footer /> ، فمن المحتمل أن نرى استخدام المزيد من المكونات بالإضافة إلى ما يشبه ترميز HTML.

 استيراد رد من "رد فعل" ؛
استيراد إعلان من "../Ad" ؛
استيراد الشعار من "../assets/logo.svg" ؛

تصدير رأس الوظيفة الافتراضية () {
إرجاع (
<header className = "app-header">
<إعلان />
<img src = {logo} className = "app-logo" alt = "logo" />
<h1 className = "app-title"> اسم الموقع </ h1>
</header>
) ؛
}

في هذا المكون <Header /> أعلاه ، يمكننا أن نرى أننا نسحب مكونًا آخر يسمى <Ad />. تحتوي معظم تطبيقات React على عدة طبقات من تداخل المكونات كما نرى في <App /> و <Header /> و <Ad />.

نرى أيضًا استخدام عناصر HTML في كود React الخاص بنا. هذا ممكن بفضل مكتبة تسمى JSX ، والتي تتيح لك كتابة "ترميز HTML" مباشرة في JavaScript الخاص بك. نظرًا لأننا نستخدم React لإنشاء واجهات مستخدم ، وتشتمل واجهات المستخدم على الويب على ترميز HTML ، فمن المنطقي أن نرى عناصر مثل HTML داخل مكونات واجهة المستخدم الخاصة بنا. سوف نستكشف JSX بعمق في هذا الكتاب.

إذا نظرنا إلى بعض التعليمات البرمجية من تطبيق React بسيط تم إنشاؤه باستخدام React 360 ، مكتبة React's VR ، فإن المكونات الفعلية التي نسميها ستكون مختلفة ، لكن بنية المكون لا تزال موجودة.

 استيراد رد من "رد فعل" ؛
يستورد {
  نص،
  رأي،
  VrButton ،
} من "رد فعل 360" ؛

يمتد عرض الشرائح للفئة React.Component {
  // تمت إزالة الرمز للإيجاز
  إرجاع (
    <عرض النمط = {styles.wrapper}>
      <عرض النمط = {styles.controls}>
        <VrButton onClick = {this.prevPhoto}>
          <Text> {'السابق'} </Text>
        </VrButton>
        <VrButton onClick = {this.nextPhoto}>
         <Text> {'Next'} </Text>
        </VrButton>
      <عرض>
        <Text style = {styles.title}> {current.title} </Text>
      </View>
    </View>
  ) ؛
}

ينشئ الكود أعلاه عدة طبقات من عرض 360 مع بعض الأزرار والنصوص المتراكبة. في حين أن الكود الفعلي قد لا يكون منطقيًا تمامًا ، يجب أن يكون واضحًا أن لدينا العديد من المكونات المتداخلة التي تمثل العرض والأزرار والنص.

هذا مثال جيد لأنه يمكنك أن ترى كيف يُعاد استخدام نفس المكونات بطرق مختلفة بتمريرها معلمات مختلفة ، أو ما تسميه React props. يعد فهم كيفية مرور البيانات عبر مكونات React أمرًا مهمًا لفهم بنية المكون النموذجية المستخدمة في البناء باستخدام React.


شرح تدفق بيانات التفاعل

تتبع React اصطلاحًا يتمثل في الحصول على البيانات وتعيينها عند أعلى نقطة ضرورية في التسلسل الهرمي للمكونات لتمرير البيانات في اتجاه واحد لأسفل عبر التطبيق ، فلنلقِ نظرة على هذا المثال وتخيل بعض أنواع البيانات التي قد نحتاجها لمكونات مختلفة.

 وظيفة التطبيق () {
  إرجاع(
    <جزء رد>
      <رأس />
      <المحتوى />
      <الشريط الجانبي />
      <تذييل />
    </ رد جزء>
  ) ؛
}

قد يلزم توفر شيء مثل اسم الموقع لكل من <Header /> و <Footer />. يجب أن يتم تمرير المحتوى الرئيسي لصفحة معينة إلى <المحتوى />. قد تحتاج بعض بيانات الأداة الإضافية إلى الانتقال إلى <الشريط الجانبي />.

 وظيفة التطبيق () {
  const siteTitle = getSiteTitle () ؛
  أدوات const = getWidgets () ؛
  const mainContent = getPageContent () ،
  إرجاع(
    <جزء رد>
      <Header siteTitle = {siteTitle} />
      <Content mainContent = {mainContent} />
      <أدوات الشريط الجانبي = {الحاجيات} />
      <Footer siteTitle = {siteTitle} />
    </ رد جزء>
  ) ؛
}

هذا الاصطلاح الخاص بتكوين أسماء السمات وتعيين قيمة لها هو كيفية تمرير البيانات إلى المكون.

الآن يمتلك <Header /> و <Footer /> حق الوصول إلى siteTitle ، ولدى <المحتوى /> حق الوصول إلى المحتوى الرئيسي ، و <الشريط الجانبي /> لديه حق الوصول إلى الأدوات التي يحتاجها.

ملاحظة مهمة هي أن هذا النمط من تمرير البيانات إلى أحد المكونات يمرر البيانات بمستوى واحد فقط. لن تتمكن المكونات الموجودة داخل <Header /> من الوصول تلقائيًا إلى siteTitle.

 رأس الوظيفة (الدعائم) {
  إرجاع(
    <رأس>
      <p> يمكننا مشاهدة {props.siteTitle} هنا. </ p>
      <PageHeader siteTitle = {props.siteTitle} />
      <PageSubHeader />
    </header>
  ) ؛
}

يمكنك أن ترى هنا أنه داخل <Header /> يمكننا استدعاء props.siteTitle والوصول إلى تلك القيمة التي مررناها إليه. ومع ذلك ، إذا أردنا الوصول إلى siteTitle داخل مكون <PageHeader /> ، فسيتعين علينا تمرير هذه المعلومات يدويًا أيضًا.

عندما يتلقى المكوِّن قيمة كخاصية ، لا يجب تعديلها. يجب أن تمر الدعائم عبر شجرة مكون كبيانات غير قابلة للتغيير. هذا يضمن أن أي مكون يشير إلى خاصيات ، يشير إلى نفس القيمة كأصل للمكونات الفرعية.

يجب تغيير قيمة الخاصية فقط في المكون الذي حدد قيمة الخاصية في الأصل وبدأ في تمريرها لأسفل عبر شجرة المكونات. في المثال أعلاه ، يمكن للمكوِّن <App /> تغيير قيمة siteTitle ، ولكن لا ينبغي أن يغير المكونان <Header /> أو <PageHeader />.

لفهم تدفق كيفية تحديث البيانات الديناميكية في تطبيق React ، يتضمن مناقشة الحالة وكيف يمكن تمرير معالجات الأحداث كدعامات.


وأوضح الدول المكونة رد فعل

كما تعلمنا ، تتدفق البيانات دون تغيير من خلال المكونات كدعامات. يتم تعيين البيانات على أعلى مكون في الشجرة اللازمة لتمرير جميع مكونات الأطفال إلى المعلومات المطلوبة كدعامات.

في بعض الحالات ، يتم تلقي هذه البيانات مرة واحدة ولا يلزم تغييرها. في كثير من الحالات ، يجب أن تظل هذه البيانات ديناميكية ولديها القدرة على التحديث في أي وقت معين وأن ينعكس هذا التحديث في جميع المكونات الفرعية.

لتتبع البيانات التي تتغير في React ، لدينا كائن حالة React ومجموعة من الوظائف المساعدة لتحديث قيمة الحالة.

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

 يمتد عداد الفئة المكون {
  الدولة = {
    عداد: 0
  } ؛

  handleCount = () => {
    this.setState ({
      العداد: this.state.counter + 1
    }) ؛
  } ؛

  يقدم - يجعل() {
    إرجاع (
      <div>
        <h1> {this.state.counter} </h1>
        <button onClick = {this.handleCount}> عد !! </ زر>
      </div>
    ) ؛
  }
}

من المهم الآن ملاحظة أن هذه الحالة مخصصة لهذا المكون فقط. لن تكون قيمة الحالة في العداد متاحة للمكونات الفرعية أو الأصل.

لذلك في مثال أكثر تعقيدًا ، كما هو موضح أدناه ، سيتعين علينا تمرير قيمة Counter down كدعم إلى العنصر الفرعي.

 يمتد عداد الفئة المكون {
  الدولة = {
    العد: 0
  } ؛

  handleCount = () => {
    this.setState ({
      العد: this.state.count + 1
    }) ؛
  } ؛

  يقدم - يجعل() {
    إرجاع (
      <div>
        <PageHeader count = {this.state.count} />
        <button onClick = {this.handleCount}> عد !! </ زر>
      </div>
    ) ؛
  }
}

يتم تحديث خاصية العد <PageHeader /> في كل مرة نقوم فيها بتحديث الحالة في مكون <Counter />

 الوظيفة PageHeader (الدعائم) {
  إرجاع <h1> {props.count} </h1> ؛ 
}

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

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

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

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

تحديث الدول المكونة في React

الآن ، ماذا يحدث عندما نريد تشغيل الحالة ليتم تحديثها من مكون فرعي؟

تخيل ، على سبيل المثال ، أنه مع المثال أعلاه أردنا أن يكون لدينا مكون <Button /> بدلاً من الزر الثابت المشفر في مكون <Counter /> الرئيسي؟ هذا في الواقع شائع جدًا في التطبيقات المعقدة.

الحل لهذا ، في عالم React ، هو تمرير دالة معالج الأحداث التي تُحدِّث الحالة مع setState أسفل كعنصر خاص. ثم يمكن استدعاؤه من أي مكون فرعي ، لكن الإجراء سيحدث في المكون الأصلي الذي يحدد الحالة ولديه القدرة على تحديثه أيضًا. توجد أنماط أخرى لهذا ، ولكن هذا النهج هو أبسط.

إذا لم تكن معتادًا على تمرير الدوال كمعلمات ، فهي صالحة تمامًا لجافا سكريبت الفانيليا.

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

هذا مثال لما سيبدو عليه ذلك.

 يمتد عداد الفئة المكون {
  الدولة = {
    العد: 0
  } ؛

  handleCount = () => {
    this.setState ({
      العد: this.state.count + 1
    }) ؛
  } ؛

  يقدم - يجعل() {
    إرجاع (
      <div>
        <PageHeader count = {this.state.count} />
        <Button handleCount = {this.handleCount} />        
      </div>
    ) ؛
  }
}

الوظيفة PageHeader (الدعائم) { 
  إرجاع( 
    <h1> {props.count} </h1>
 ) ؛ 
}

زر الوظيفة (الدعائم) {
  إرجاع(
    <button onClick = {props.handleCount}> العد !! </ زر>  
  ) ؛
}

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

إذا كانت الحالة بحاجة إلى التحديث من مكون بخلاف المكان الذي تم تعيينه فيه في الأصل ، فيمكن عندئذٍ تمرير معالج الحدث إلى المكون الفرعي الضروري كعنصر خاص. هذا يحافظ على البيانات غير قابلة للتغيير وتتدفق في اتجاه واحد لأنه حتى إذا أدى أحد المكونات الفرعية إلى حدوث تغيير ، فإن هذا التغيير يحدث في مكان أعلى في المكون الأصلي.

عندما نقوم بتعيين قيمة خاصيّة لشيء ما من حالة ، كما هو مذكور أدناه ، سيتم تحديث قيمة الخاصية تلقائيًا كلما تغيرت الحالة.

 <PageHeader counter = {this.state.count} />

سيتلقى أي مكون تابع آخر يشير إلى قيمة الخاصية التحديث تلقائيًا. هذا هو جمال تدفق البيانات في React.

قد يستغرق هذا بعض الوقت لتعتاد عليه اعتمادًا على كيفية تعاملك مع مشكلات مثل هذه مع JavaScript في الماضي. ومع ذلك ، يجب أن يكون كل هذا بمثابة نقطة انطلاق جيدة لنا حتى نتمكن من التعمق أكثر في شرح React.