ساخت یک کامپوننت ساده و واقعی در React

Building a Simple and Real Component in React

ساخت یک کامپوننت ساده و واقعی

تا اینجای کار با مفاهیم اولیه و پایه react (مانند JSX) به خوبی آشنا شده ایم و حالا وقت آن است که یک کامپوننت واقعی برای خودمان بسازیم. برای شروع در پوشه src از پروژه مان یک پوشه دیگر به نام Person می سازیم. قراردادی بین برنامه نویسان react وجود دارد که حرف اول در نام کامپوننت ها باید همیشه بزرگ باشد (یعنی Person و نه person) اما شما مجبور به پیروی از آن نیستید. با این حال از آنجا که این موضوع یک قرار داد فراگیر است ما هم به آن احترام گذاشته و ساختار فایل های خودمان را بر همین اساس ایجاد می کنیم. ما می خواهیم در این پوشه کامپوننتی بسازیم که در آن اطلاعاتی راجع به یک فرد نمایش داده شود.

درون پوشه Person فایلی به نام Person.js ایجاد می کنیم. از جلسات قبل یاد گرفته ایم که برای ساخت یک کامپوننت باید از کتابخانه react استفاده کرده و کلاس component را extend کنیم. کدهای جلسه قبل را یادتان می آید؟

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hi, I'm a React App!</h1>
        <p>This is really working!</p>
      </div>
    );
    // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

همانطور که می بینید در خط اول ابتدا کتابخانه react را import کرده ایم و سپس کلاس Component را extend کرده ایم (با کلاس App). ما می توانیم از همین روش برای ساخت کامپوننت ها استفاده کنیم، مخصوصا زمانی که به مبحث state برسیم (که به شما کمک می کند تا کامپوننت هایتان را تغییر دهید)، اما در اکثر اوقات باید از روش دیگری استفاده کنید: یک تابع جاوا اسکریپتی!

بله یک تابع ساده در جاوا اسکریپت! چرا؟ به این دلیل که در ساده ترین حالت، هر کامپوننت یک تابع جاوا اسکریپتی است که JSX خاصی را برمی گرداند. شما می توانید این تابع را به شکل زیر تعریف کنید:

function person () {
    // return some JSX
}

همچنین می توانید از همان روش ES5 استفاده کنید:

var person = function () {
    // return some JSX
}

این روش ها کاملا عملی است اما ما در این دوره از ES6 استفاده خواهیم کرد چرا که حالت استاندارد و توصیه شده برای نوشتن برنامه های react است. بنابراین می گوییم:

const person = () => {
    return <p>I'm a person!</p>
}

نکات این کد:

  • از آنجا که قصد تغییر این کد را نداریم آن را درون یک ثابت (const) قرار داده ایم.
  • قرارداد این است که نام توابع در جاوا اسکریپت با حروف کوچک باشد اما شما الزامی برای پیروی از آن ندارید. ما سعی می کنیم در این دوره تمام استاندارد های ممکن را رعایت کنیم.
  • این تابع به جز برگرداندن JSX کاری انجام نمی دهد.

اگر به تابع دقت کنید متوجه می شوید که چیزی کم است. بله ما هنوز کتابخانه react را import نکرده ایم! مسئله این است که بدون react کد های JSX ها تبدیل به HTML نمی شوند و در واقع پر از خطا خواهند بود. بنابراین بالا تر از تابع می نویسیم:

import React from 'react';

در واقع React (با R بزرگ) را از پکیج react وارد کرده ایم. برخلاف کد های جلسه قبل نیازی به استفاده از {component} نداریم چرا که به جای آن از یک تابع ساده استفاده کرده ایم.

در آخر باید این تابع را export کنیم بنابراین:

export default person;

حالا فایل را ذخیره کنید.

از این به بعد می توانیم از این کامپوننت ساده در فایل های دیگر پروژه مان استفاده کنیم. البته فعلا فقط یک کامپوننت ریشه ای (App.js) داریم بنابراین در همانجا import اش می کنیم:

import Person from './Person/Person'

نکات این کد:

  • Person اول با P بزرگ همان کامپوننت شما است و Person آخر اشاره به فایل js دارد اما از آنجا که اسکریپت های ما خودشان پسوند js را اضافه می کنند ما دیگر نیازی به نوشتن این پسوند نداریم.
  • اضافه کردن ./ در ابتدای آدرس به این دلیل است که آدرس ما از نوع نسبی (relative) است نه absolute.
  • Person اول (کامپوننت) باید حتما در هنگام import شدن دارای حرف اول بزرگ (P و نه p) باشد چرا که در react تمامی عناصری که با حرف کوچک شروع شوند (مانند div و h1 و ...) برای تبدیل شدن به HTML رزرو شده اند. اگر Person حرف اول بزرگ نداشته باشد react آن را به عنوان عنصر HTML شناسایی خواهد کرد!

بنابراین می توانیم به این صورت Person را وارد کد JSX کنیم:

import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person';

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hi, I'm a React App!</h1>
        <p>This is really working!</p>
        <Person></Person>
      </div>
    );
    // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

نکته: از آنجایی که در این مثال هیچ عنصر دیگری درون <Person> قرار نداده ایم (مبحث nesting) می توانیم از تگ های self-closing استفاده کنیم:

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hi, I'm a React App!</h1>
        <p>This is really working!</p>
        <Person />
      </div>
    );
    // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

در جلسات بعدی بیشتر در مورد مبحث nesting صحبت خواهیم کرد.

حالا اگر این فایل را ذخیره کنید و به مرورگر بروید (انتظار دارم که npm start را که در جلسات قبل به شما آموزش داده ایم باز کرده باشید) متوجه می شوید:

استفاده از یک کامپوننت تازه ساخته شده در کامپوننت ریشه ای
استفاده از یک کامپوننت تازه ساخته شده در کامپوننت ریشه ای

سوال: چرا کدهایی که درون تابع گذاشتیم را مستقیما به JSX اضافه نکردیم و از مسیر طولانی ساختن یک کامپوننت جدید با استفاده از یک تابع انجامش دادیم؟

پاسخ: دلایل مختلفی برای این کار داریم؛ اولا با استفاده از این روش می توانیم کامپوننت های خود را جداگانه و به صورت ماژولار در فایل های جدا قرار دهیم تا مدیریت و نگهداری از آن ها بسیار آسان تر باشد. در غیر این صورت باید تمام کد ها را درون App.js قرار دهیم که بسیار شلوغ خواهد شد. دلیل دوم این است که کامپوننت های جداگانه (به شکلی که ما ساختیم) هم قابلیت استفاده مجدد دارند و هم قابل تنظیم و پیکربندی هستند!

در مورد بخش «قابل تنظیم و پیکربندی» بعدا صحبت می کنیم اما در مورد قابلیت استفاده مجدد می توانیم آن را به سادگی کپی کنیم:

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hi, I'm a React App!</h1>
        <p>This is really working!</p>
        <Person />
        <Person />
        <Person />
      </div>
    );
    // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

نتیجه نیز همان چیزی خواهد بود که فکر می کنید، یعنی عبارت I'm a person! سه بار تکرار خواهد شد.

جمع بندی مباحث تا این قسمت

- react به شکل ساده اش، چیزی به جز مجموعه ای از کامپوننت ها نیست. بنابراین یک برنامه که با react نوشته شده است باید یک کامپوننت ریشه ای (root component) داشته باشد (در پروژه ساده ما همان App.js) که درون خود تعداد نامحدودی کامپوننت می گیرد.

- JSX به هیچ عنوان HTML نیست اما از نظر ظاهری شبیه آن است (استفاده از className به جای class و ... شواهد دال بر این موضوع اند). JSX کد جاوا اسکریپتی است که به شما اجازه می دهد به جای هر بار فراخوانی تابع React.createElement(…) از کد های شبیه به HTML استفاده کنید.

- دو نوع کامپوننت react وجود دارد:

نوع اول - functional components (کامپوننت های کاربردی): این نوع کامپوننت ها به نام های presentational و dumb و stateless نیز شناخته می شوند که به ترتیب معانی «نمایشی» و «غیر هوشمند» و «بدون وضعیت» را می دهند. مثال:

const cmp = () => {
  return <div>some JSX here</div>
}

نوع دوم - class-based components (کامپوننت های کلاس-محور): این نوع کامپوننت ها به نام های container و smart و stateful نیز شناخته می شوند که به ترتیب معانی «نگهدارنده» و «هوشمند» و «با وضعیت» را می دهند. مثال:

class Cmp extends Component {
  render() {
    return <div>some JSX here</div>
  }

در طول دوره با تفاوت های هر دو نوع کامپوننت آشنا خواهیم شد اما باید توجه کنید که به غیر از موارد جزئی باید در حد ممکن از نوع اول (کامپوننت های کاربردی) استفاده شود. امیدوارم درک خوبی از تفاوت این دو نوع کامپوننت به دست آورده باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش ری اکت توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.