كيفية بناء نسخة أساسية من Product Hunt باستخدام React

يشارك هذا المثال والتصميم ما تعلمته من كتاب Fullstack React. أوصي به بشدة كمورد جيد لتعلم React وتكنولوجيات النظام البيئي. التحقق من ذلك هنا: fullstackreact.com.

تخيل أنه كمطور ، لقد تم تكليفك بإنشاء MVP لمنتج بدء التشغيل الذي يحتاج إلى إظهاره للمستثمرين المحتملين.

التطبيق عبارة عن تطبيق للتصويت مستوحى من Product Hunt و Reddit. في التطبيق ، يتم عرض المنتجات في مجموعة. يمكن للمستخدمين التصويت على أفضل المنتجات ، وسيقوم التطبيق بفرزها تلقائيًا وفقًا لعدد الأصوات ، مع وضع أعلى الأصوات قبل أدنى مستوى.

ميزات التطبيق الذي سنقوم ببنائه بسيطة للغاية:

  • يمكن للمستخدمين عرض المنتجات الحالية / المعروضة.
  • يمكن للمستخدمين التصويت على المنتجات التي تسعدهم
  • يتم فرز المنتجات تلقائيًا وفقًا لعدد الأصوات.

يمكنك عرض التجريبي هنا.

الخطوة 1: أول الأشياء أولا

Fist of all ، توجه إلى Github وقم بتنزيل مجلد البدء الذي قمت بإنشائه بالفعل من خلال الإعداد اللازم لتطبيقنا هنا. انسخ عنوان URL الذي يوفره الزر clone / download الأخضر وقم بتشغيله في المسار المفضل لديك في سطر الأوامر. يجب أن يكون لديك بوابة مثبتة بالفعل.

بوابة استنساخ URL

بمجرد تنزيل المجلد ، افتحه في محرر التعليمات البرمجية ولاحظ ملفات المجلد وهيكله. يبدو مثل هذا:

├───src
| ├───app.js
| ├───seed.js
| ├───style.css
└───vendor
    ├───bootstrap-3.3.7-حي
    ├───font-رهيبة-4.7.0
    ├───react.js
    ├───react-dom.js
    └───babel-standalone.js

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

تحت مجلد src ، توجد ملفات app.js و seed.js. ملف app.js هو المكان الذي سنكتب فيه معظم الشفرة لتطبيقنا. يحتوي ملف seed.js بالفعل على مجموعة بيانات المنتجات المراد عرضها.

يحتوي ملف seed.js الخاص بنا على الكود التالي

window.Seed = (function () {
    وظيفة إنشاء VOTOUNT () {
      return Math.floor ((Math.random () * 50) + 15) ؛
    }
    منتجات const = [
      {
        المعرف: 1 ،
        العنوان: "سطل أصفر" ،
        الوصف: "بناء على الخبرة بناء قلعة الرمال." ،
        عنوان url: '#' ،
        تصويت: إنشاء VOTOKUNT () ،
        submitterAvatarUrl: 'images / avatars / daniel.jpg' ،
        productImageUrl: 'images / products / image-aqua.png' ،
      }،
                                ...
    ].
    return {products: products}؛
  } ())؛

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

تقوم دالة Seed أخيرًا بإرجاع كائن به خاصية المنتجات وقيمة المنتجات. هذا يعني أنه إذا قمنا بتنفيذ Seed.products ، فيجب أن يتم إرجاع كل كائن منتج إلينا.

ملف react.js هو الكود الذي يحتوي على لب React نفسه. أيضًا ، react-dom.js هو الكود الذي يساعدنا على تقديم مكونات React التي أنشأناها في HTML DOM. أخيرًا ، babel-standalone.js هو رمز Babel الذي ينقل كود JSX و ES6 المتقدم الذي سنعمل معه إلى كود ES5 (مواصفات JavaScript الأكثر شيوعًا التي تدعمها معظم المتصفحات القديمة والحالية اليوم).

الخطوة 2: إنشاء مكونات

نحن بحاجة إلى إنشاء مكونين React. سنقوم بالاتصال بقائمة Product Productist للمكون الرئيسي ، وستكون Procuct هي مجموعة المكونات الفرعية للأطفال.

داخل ملف app.js ، قم بإنشاء المكون الأصل عن طريق القيام بذلك:

يمتد ProductList لفئة React.Component {
    يجعل() {
        منتجات const = Seed.products.map ((product) => (
            <المنتج
            ID = {product.id}
            عنوان = {product.title}
            وصف = {product.description}
            URL = {product.url}
            الأصوات = {product.votes}
            submitterAvatarUrl = {product.submitterAvatarUrl}
            productImageUrl = {product.productImageUrl}
            />
        ))؛
        إرجاع (
            
                

المنتجات الشائعة                 <ساعة />                 {منتجات}                      )؛     } } ReactDOM.render (، document.getElementById ('content'))؛

في المكون الأصل ، نعتزم إنشاء مكون تابع يستند إلى كل كائن يمكن الوصول إليه من Seed.products. لذلك أنشأنا بعض الدعائم. الآن دعنا نعلن في الواقع أن العنصر الفرعي لا يزال في نفس الملف المسمى المنتج:

فئة المنتج يمتد React.Component {
    يجعل() {
        إرجاع (
          
            
            
                
                
                                                      
                                                                                       {this.props.votes}                                  
                                             {this.props.title}                                          

{} this.props.description                                                     

                 مقدم من:                                                                                             )؛       } }

نحن قادرون على الرجوع إلى React.Component و ReactDOM.render لأننا قمنا بالفعل بتحميل ملفات react.js و react-dom.js. إنها متاحة للاستخدام على الرغم من أننا حاليًا في ملف app.js. بعد إنشاء المكون ، يعرض ReactDOM.render (whatComponent ، أين) إلى DOM.

تشغيل الخادم المباشر الخاص بك ، يجب أن يكون لديك الشاشة التالية:

مكونات ثابتة

الخطوة 3: إضافة التفاعل

حتى الآن ، تمكنا من ترميز مكونات تطبيقنا - لكنها لا تزال ثابتة. كيف يمكننا أن نجعلها تفاعلية؟

في تشفير تطبيقات React ، اتبع هذه العملية العامة:

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

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

معرفة حالتنا ، أين نهيئها؟ الدول في رد الفعل مكتفية ذاتيا في بعض المكونات ، على عكس الدعائم التي يتم تمريرها. عدد الأصوات كدولة مملوك لـ <المنتج /> ، لكن منذ جمع المنتجات التي أنشأناها من ، نقوم بتهيئة الحالة هناك. في ، قم بذلك قبل طريقة التقديم ():

البناء() {
        ممتاز()؛
        هذا. الدولة = {
            منتجات: []
        }
    }

عند تهيئة الحالة في أحد المكونات ، نحاول تحديد الشكل الذي يجب أن يبدو عليه مع إبقائه فارغًا. منتجاتنا هي مجموعة ، لذلك نحن نستخدم مجموعة فارغة. نحن نقوم بتهيئته داخل constructor () {} ، لأن هذا الجزء من الشفرة يتم تشغيله عند إنشاء المكون الخاص بنا.

لنجعل مكوننا يقرأ المنتجات من حالته الخاصة بدلاً من الملف. إضافة:
 componentDidMount () {
 this.setState ({products: Seed.products})
 }
 لضبط الدولة للاستخدام. أيضًا قم بتحديث منتجات const = Seed.products إلى منتجات const = this.state.products. لجعل JavaScript يصنفها وفقًا لأعلى عدد من الأصوات ، اكتب هذا بدلاً من ذلك:

منتجات const = this.state.products.sort ((a، b) {
    ب - الأصوات - أ
})؛

JavaScript JavaScript ()؛ يستخدم وظيفة مقارنة داخل. يمكنك معرفة ذلك في وثائق.

الخطوة 4: التعامل مع الاقتراع

دعنا نتوجه إلى الارتباط التشعبي الذي يحيط برمز الخط الرائع ، إنشاء علامة ، وإنشاء وظيفة باستخدام onClick.


    
 

بعد أن حددنا الوظيفة ، يتيح لك إنشائها بالفعل. داخل مكون المنتج ، قم بإنشاء passTheId ()؛ وظيفة:

البناء() {
        ممتاز()؛
        this.passTheId = this.passTheId.bind (this)؛
    }
    passTheId () {
        console.log ("سيتم تمرير المعرف") ؛
    }

لقد ربطنا هذه الكلمة بالكلمة الرئيسية ، لأن الوظائف المضمنة مثل render () هي فقط التي يمكنها الوصول إلى استخدام هذه الكلمة.

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

handleProductUpVote = (productId) => {
    const nextProducts = this.state.products.map ((product) => {
      if (product.id === productId) {
        إرجاع Object.assign ({} ، المنتج ، {
          الأصوات: product.votes + 1 ،
        })؛
      } آخر {
        عودة المنتج ؛
      }
    })؛
    this.setState ({
      المنتجات: المنتجات التالية ،
    })؛
  }

يجب أن تعامل الدول في React غير قابل للتغيير. وهذا هو ، لا ينبغي تعديلها مباشرة. ستعمل الوظيفة أعلاه على ذلك باستخدام Object.assign () في JavaScript ؛ عن طريق إنشاء مجموعة جديدة على ما يبدو تسمى nextProducts. هذا مشابه للحالة الحالية ، لكن لديه تغيير في عدد الأصوات. nextProductsis ثم تعيين كحالة جديدة. يبدو غريباً القيام بالأشياء بهذه الطريقة ، لكن هذا ما يوصي به فريق React لتحسين الأداء.

نريد تمرير معرّف المنتج من مكون المنتج الفرعي إلى مكون ProductList الأصلي ، لذلك يتيح إتاحة المقبض productUpVote للطفل كدعائم:

منتج ثابتالمكونات = products.map ((المنتج) => (
      <المنتج
        key = {'product-' + product.id}
        ID = {product.id}
        عنوان = {product.title}
        وصف = {product.description}
        URL = {product.url}
        الأصوات = {product.votes}
        submitterAvatarUrl = {product.submitterAvatarUrl}
        productImageUrl = {product.productImageUrl}
        onVote = {this.handleProductUpVote}
      />
    ))؛

أضفنا onVote = {this.handleProductUpVote}. لذلك على مستوى الطفل ، يمكننا الوصول إليه من خلال هذا الموقع

passTheId () {
        console.log ("سيتم تمرير المعرف") ؛
        this.props.onVote (this.props.id)
    }

يجب أن يبدو ملف app.js بأكمله كما يلي:

يمتد ProductList لفئة React.Component {
    الولاية = {
        منتجات: []،
      }؛
      componentDidMount () {
        this.setState ({products: Seed.products}) ؛
      }
      handleProductUpVote = (productId) => {
        const nextProducts = this.state.products.map ((product) => {
          if (product.id === productId) {
            إرجاع Object.assign ({} ، المنتج ، {
              الأصوات: product.votes + 1 ،
            })؛
          } آخر {
            عودة المنتج ؛
          }
        })؛
        this.setState ({
          المنتجات: المنتجات التالية ،
        })؛
      }
    يجعل() {
        منتجات const = this.state.products.sort ((a، b) => (
            ب - الأصوات - أ
        ))؛
        منتج ثابتالمكونات = products.map ((المنتج) => (
            <المنتج
              key = {'product-' + product.id}
              ID = {product.id}
              عنوان = {product.title}
              وصف = {product.description}
              URL = {product.url}
              الأصوات = {product.votes}
              submitterAvatarUrl = {product.submitterAvatarUrl}
              productImageUrl = {product.productImageUrl}
              onVote = {this.handleProductUpVote}
            />
          ))؛
        إرجاع (
            
                

المنتجات الشائعة                 <ساعة />                 {productComponents}                      )؛     } }

فئة المنتج يمتد React.Component {
    البناء() {
        ممتاز()؛
        this.passTheId = this.passTheId.bind (this)؛
    }
    passTheId () {
        console.log ("سيتم تمرير المعرف") ؛
        this.props.onVote (this.props.id)؛
    }
    يجعل() {
        إرجاع (
          
            
            
                
                
                                     
                
                                                                                       {this.props.votes}                                  
                                             {this.props.title}                                          

                        {this.props.description}                                                     

                 مقدم من:                                               
            
            
          
        )؛
      }
}
ReactDOM.render (، document.getElementById ('content'))؛

قم بتحديث متصفحك وسترى تطبيق العمل. عرض التجريبي.

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

إذا كنت قد استمتعت بهذا المقال ، أعطني بعض التصفيقات حتى يرى المزيد من الناس ذلك. شكرا لقرائتك.

يمكنك قراءة المزيد من كتاباتي على مدونتي: Stellar Code.