آشنایی با JSX و محدودیت‌های آن

Familiarity with JSX and its Limitations

23 بهمن 1399
آشنایی با JSX و محدودیت های آن

با سلام و خسته نباشید خدمت شما همراهان گرامی. در قسمت قبل با تنها کامپوننت موجود در فایل هایمان آشنا شدیم:

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hi, I'm a React App!</h1>
      </div>
    );
  }
}

برای شروع این جلسه کدهای JSX داخل این کامپوننت را کامنت کنید (کلیدهای / + Ctrl) تا فعلا غیرفعال شوند:

class App extends Component {
  render() {
    // return (
    //   <div className="App">
    //     <h1>Hi, I'm a React App!</h1>
    //   </div>
    // );
  }
}

ما می خواهیم چیز دیگری را return کنیم. بنابراین ابتدا شیء react را صدا می زنیم و سپس درخواست یک متد خاص به نام createElement را داریم:

React.createElement()

این متد بی نهایت آرگومان می گیرد که حداقل سه مورد را باید به آن بدهیم (بنابراین حداقل 3 آرگومان)؛ آرگومان اول همان عنصری است که می خواهیم در DOM نمایش داده شود. می توانیم آن را یک عنصر عادی HTML (مثلا یک div) در نظر بگیریم و یا اینکه یکی کامپوننت های خاص خودتان باشد (اگر از قبل کامپوننتی دارید). از آنجایی که ما هیچ کامپوننت دیگری نداریم بنابراین از یک div ساده استفاده می کنیم.

آرگومان دوم یک شیء جاوا اسکریپتی است که تنظیمات پیکربندی را درون خود دارد. ما فعلا مقدار null را به آن پاس می دهیم چرا  که فعلا قصد پیکربندی چیزی را نداریم. آرگومان سوم نیز تعداد فرزندان این عنصر است؛ یعنی چه چیزی درون این div قرار بگیرد؛ برای مثال ما همان h1 خود را درون آن می گذاریم:

render() {
    // return (
    //   <div className="App">
    //     <h1>Hi, I'm a React App!</h1>
    //   </div>
    // );
    return React.createElement('div', null, 'h1', 'Hi, I\'m a React App!!!');
  }

توجه داشته باشید که باید آن را return کنیم. دلیل استفاده از backslash در کلمه I’m این است که علامت ‘ یک single quote است و کل رشته باید درون یک جفت quote باشد. به همین دلیل این quote اضافی را با یک backslash فراری داده ایم (به آن escape کردن می گویند). شما می توانید هر تعداد آرگومان دیگر که خواستید (به همین شکل بالا - با جدا کردن توسط ویرگول انگلیسی) به آن بدهید. خروجی ما در مرورگر این متن خواهد بود:

h1Hi, I'm a React App!!!

حالا اگر در مرورگر خود f12 را بزنیم می بینیم:

نتیجه ی کد react - شماره 1
نتیجه کد react - شماره 1

بنابراین دو text node (متن) در صفحه ایجاد کرده ایم و h1 به صورت تگ اضافه نشده است. اگر بخواهیم h1 نیز به عنوان تگ اضافه شود باید بگوییم:

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

یعنی createElement را دوباره درون createElement صدا بزنیم. حالا خروجی بدین شکل خواهد بود:

Does this work now?

نتیجه ی کد react - شماره 2
نتیجه کد react - شماره 2

بنابراین h1 واقعا به صورت یک عنصر HTML نمایش داده شده است.

حالا مشکل بعدی را باید حل کنیم. در فایل های استایل دهی، استایل مربوط به کلاس App. را باقی گذاشتیم (وسط بودن متن) اما اینجا اعمال نشده است و خروجی ما در سمت چپ نمایش داده می شود. دلیل این مسئله واضح است؛ در کدهایمان به تگ h1 هیچ کلاسی نداده ایم.

اینجا شیء پیکربندی وارد کار می شود! می توانیم بگوییم:

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

نکته: در react به جای class از className استفاده می کنیم و دلیلش را در جلسات بعد توضیح خواهم داد.

حالا کلاس CSS اعمال شده و متن ما به وسط صفحه می رود:

نتیجه ی کد react - شماره 3
نتیجه کد react - شماره 3

آیا متوجه شدید چه اتفاقی افتاد؟ کد زیر را ببینید:

    return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?'));

این کد را همین حالا نوشتیم. این کد دقیقا معادل کد JSX ای بود که کامنت کردیم:

// return (
    //   <div className="App">
    //     <h1>Hi, I'm a React App!</h1>
    //   </div>
    // );

در واقع ابزارهایی که در پروژه ما هستند و ما آن ها را نصب کردیم این کد (کد JSX) را در آخر به کدی که ما نوشتیم تبدیل (کامپایل شدن) می کنند.

مطمئن هستم که متوجه دلیل وجود JSX شده اید؛ کدنویسی به این شکل و بدون JSX واقعا خسته کننده و طاقت فرسا است، مخصوصا زمانی که ده ها عنصر تو در تو داشته باشیم فهمیدن کدها غیر ممکن می شود. به همین دلیل JSX به وجود آمده است و ما هم در طول این دوره از روش استاندارد، یعنی استفاده از JSX، استفاده خواهیم کرد.

محدودیت های JSX

در استفاده از JSX با برخی از محدودیت ها روبرو هستیم که دوست دارم با آن ها آشنا شوید. به طور مثال استفاده از همان className به جای class یکی از این محدودیت ها است. دلیل این محدودیت این است که کلمه class یک کلمه رزرو شده و خاص در جاوا اسکریپت است بنابراین اگر در آن از واژه class استفاده کنیم، کد ما به هم می ریزد. به کد زیر توجه کنید:

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

در خط اول این کد از همین کلیدواژه جاوا اسکریپت استفاده کرده ایم (class App) بنابراین نمی توان از آن در JSX استفاده کرد. البته در مرورگر این کد تبدیل به class می شود و جای نگرانی نیست، فقط هنگام نوشتن JSX نمی توان از آن استفاده کرد.

توجه داشته باشید که بر اساس مطالب قبلی می دانیم که JSX به هیچ عنوان HTML نیست. JSX شبیه به HTML است اما در واقع متنی است که react آن را گرفته و بعدا تبدیل به HTML می کند.

محدودیت دیگری که داریم این است که کد JSX باید فقط و فقط یک عنصر root داشته باشد و بقیه عناصر درون آن قرار بگیرند بنابراین کد زیر غلط است:

return (
      <div className="App">
        <h1>Hi, I'm a React App!</h1>
      </div>
      <h1>Another heading</h1>
    );

چرا؟ به این دلیل که div ما (کلاس App) یک عنصر برادر برای h1 محسوب می شود (رابطه برادری عناصر HTML - کنار هم بودن) اما ما گفتیم که فقط و فقط یک عنصر باید وجود داشته باشد و تمامی عناصر دیگر باید درون آن قرار بگیرند (رابطه پدر و فرزندی).

البته با معرفی نسخه 16 کتابخانه React این محدودیت تا حدی از بین رفته است و می توانید این کار را انجام دهید اما بر اساس استانداردی که جا افتاده است ما هم از این قانون پیروی می کنیم و در کامپوننت را در یک div کلی قرار می دهیم. این کار از نظر استایل دهی نیز به شما کمک می کند تا کامپوننت هایتان را به شکل مرتب تری استایل دهی کنید.

سوال دیگری که ممکن است در ذهن شما باشد این است که در کد زیر چرا پس از دستور return از پرانتز استفاده می کنیم و JSX را درون آن می نویسیم:

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?'));
  }

همانطور که می دانید در جاوا اسکریپت نمی توانید از وسط کد اینتر بزنید و به خط بعدی بروید. برای جلوگیری از بروز خطا در کدهایمان از این پرانتزها استفاده می کنیم تا جاوا اسکریپت تمام JSX را به یک شکل ببیند و برای نحوه نوشتار آن (به شکل HTML و پر از new line (همان اینتر)) از ما خطا نگیرد.

امیدوارم کاملا با JSX آشنا شده و دلیل استفاده از آن را نیز درک کرده باشید. در قسمت های بعدی سعی می کنیم یک کامپوننت واقعی بسازیم و با آن کار کنیم.

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

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

امیر خ
26 اسفند 1398
با سلام استاد من ی روشی رو تست کردم جواب هم داد...حالا میخوام بگم ببینم نظر شما چیه return React.createElement('div', null,, 'Hi, I\'m a React App!!!'); اینجوری دیگه خروجی ما Hi, I’m a React App!!! . . h1 حذف می شود در واقع به عنوان المان ازش یاد میشه نه تکست... نظر شما چیه؟

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

امیر زوارمی
13 فروردین 1399
سلام دوست عزیز، بستگی به سلیقه و کاربرد برنامه ی شما داره. مثلا اگر قرار باشه از تگ h1 برای استایل دهی استفاده کنید، با حذفش دچار مشکل می شید اما توی برنامه ی شما کار می کنه، نیازی به عوض کردنش نیست. معمولا همونطور که جلو میرید متوجه اشتباهات کدنویسی می شید چون توی React خیلی از کد ها همون اول اشکال ندارن اما بعدا در همکاری با کد های دیگه اشتباه پیدا می کنن. به هر حال روش شما بد نیست و تا زمانی که کار می کنه می تونین ازش استفاده کنین.

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