روش صحیح نمایش شرطی عناصر + لیست‌ها در React

The Correct Way to Conditionally Display Elements + Lists in React

23 بهمن 1399
روش صحیح نمایش شرطی عناصر + لیست ها در react

روش صحیح نمایش مشروط محتوا

در جلسه قبل یاد گرفتیم که نمی توانیم از بلوکه if در کدهای JSX استفاده کنیم و باید به جای آن از ternary operator استفاده کرد. مشکل اینجاست که استفاده از ternary operator باعث شلوغ شدن بیش از حد کدها می شود و اگر کامپوننت ما چندین بخش مختلف داشته باشد پیدا کردن قسمت های مربوط به هر ternary operator کار سختی می شود. ما می خواهیم در این قسمت با روشی دیگر برای نمایش شرطی کدها آشنا شویم.

برای شروع ternary operator و curly braces ها را از قسمت قبل حذف کنید:

return (
      <div className="App">
        <h1>Hi, I'm a React App</h1>
        <p>This is really working!</p>
        <button
          style={style}
          onClick={this.togglePersonsHandler}>Toggle Persons
        </button>

        <div>
          <Person
            name={this.state.persons[0].name}
            age={this.state.persons[0].age} />
          <Person
            name={this.state.persons[1].name}
            age={this.state.persons[1].age}
            click={this.switchNameHandler.bind(this, 'Max!')}
            changed={this.nameChangedHandler} >My Hobbies: Racing</Person>
          <Person
            name={this.state.persons[2].name}
            age={this.state.persons[2].age} />
        </div>
      </div>
    );

نکته ای که باید از آن استفاده کنیم این است: زمانی که react می خواهد چیزی را در صفحه نمایش دهد یا آپدیت کند فقط قسمت return را برنمی گرداند بلکه هر چیزی که در تابع render باشد اجرا خواهد شد بنابراین می توانیم قبل از return کدهای مورد علاقه مان را اضافه کنیم!

بنابراین درون تابع render و بالاتر از return کد زیر را اضافه می کنیم:

    let persons = null;

    if (this.state.showPersons) {
      persons = (
        <div>
          <Person
            name={this.state.persons[0].name}
            age={this.state.persons[0].age} />
          <Person
            name={this.state.persons[1].name}
            age={this.state.persons[1].age}
            click={this.switchNameHandler.bind(this, 'Max!')}
            changed={this.nameChangedHandler} >My Hobbies: Racing</Person>
          <Person
            name={this.state.persons[2].name}
            age={this.state.persons[2].age} />
        </div>
      )
    }

در اینجا یک متغیر به نام persons ایجاد کرده ایم (شما می توانید نام دیگری انتخاب کنید) و مقدار اولیه آن را null گذاشته ایم. سپس با یک شرط if ساده مقدار persons را برابر با کدی قرار داده ایم که می خواهیم نمایش داده شود. حالا باید این کدها را از قسمت return عادی برداریم. توجه کنید، از آنجایی که در JSX نیستیم می توانیم از بلوک های if استفاده کنیم. شرط if ما این است که showPersons برابر true باشد.

حالا باید persons را در کد JSX (در return) قرار دهیم:

return (
      <div className="App">
        <h1>Hi, I'm a React App</h1>
        <p>This is really working!</p>
        <button
          style={style}
          onClick={this.togglePersonsHandler}>Toggle Persons
        </button>
        {persons}
      </div>
    );

در این حالت دقیقا به نتیجه جلسه قبل می رسیم. چرا؟ به این دلیل که هر بار react تصمیم بگیرد که DOM را refresh کند تابع render صدا زده می شود و هر بار که render صدا زده شود مقدار persons ابتدا روی null قرار می گیرد مگر اینکه showPersons مقدار true داشته باشد. showPersons نیز زمانی true می شود که روی دکمه کلیک شود. زمانی که روی دکمه کلیک شود مقدار state تغییر می کند و DOM باید دوباره render شود (رفتار react اینطور است) و زمانی که DOM دوباره render شود، وضعیت showPersons چک می شود و بر اساس آن محتوا نمایش داده شده و یا مخفی می شود.

این روش، روش استانداردتر و پیشنهاد ما برای نمایش محتوا به صورت شرطی است و در طول دوره نیز از همین روش استفاده خواهیم کرد.

نمایش لیست ها در ری اکت

حالا نوبت به نمایش لیست افراد است. در حال حاضر نمایش افراد پویا نیست بلکه افرادی از قبل تعیین شده اند (کد آن ها را به صورت دستی نوشته ایم) و با یک کلیک نمایش داده می شوند. به طور مثال اگر تعداد افراد در state بیشتر شوند تمام برنامه ما خراب می شود چرا که در قسمت if (کد JSX شرطی) فقط 3 نفر را تعیین کرده ایم. در برنامه های واقعی تعداد افراد در state از طریق پایگاه داده گرفته می شود و اصلا کنترلی روی آن نداریم تا بدانیم چند نفر هستند (ممکن است هزاران نفر باشند). بنابراین باید کدهای این قسمت را پویا کنیم.

برای انجام این کار ابتدا باید به قسمت JSX در بلوک if برویم. قبلا به شما گفته بودم که برای نمایش محتوای پویا و استفاده از کدهای جاوا اسکریپت باید از curly brace ها استفاده کنیم.

بنابراین در ایجاد باید اول از همه یک جفت curly brace قرار دهیم و سپس افرادی که در آرایه persons (در state) هستند را به آن پاس دهیم. آرایه persons در State به همراه state های دیگر:

state = {
    persons: [
      { name: 'Max', age: 28 },
      { name: 'Manu', age: 29 },
      { name: 'Stephanie', age: 26 }
    ],
    otherState: 'some other value',
    showPersons: false
  }

تابع map در جاوا اسکریپت تابعی است که یک تابع را به عنوان آرگومان می گیرد و سپس آن را روی تک تک اعضای یک آرایه اجرا می کند. در قسمت های «مروری بر ES6» در مورد آن صحبت کرده بودیم. اگر آرایه persons را مستقیما از state در قسمت JSX قرار دهیم مشکل به وجود می آید چرا که این آرایه مجموعه ای از اشیاء جاوا اسکریپتی است که قابلیت تبدیل شدن به HTML را ندارند و JSX هم نمی داند با آن ها چه کار کند. بنابراین این کار غلط است:

if (this.state.showPersons) {
      persons = (
        <div>
          {this.state.persons}
          <Person
            name={this.state.persons[0].name}
            age={this.state.persons[0].age} />
          <Person
            name={this.state.persons[1].name}
            age={this.state.persons[1].age}
            click={this.switchNameHandler.bind(this, 'Max!')}
            changed={this.nameChangedHandler} >My Hobbies: Racing</Person>
          <Person
            name={this.state.persons[2].name}
            age={this.state.persons[2].age} />
        </div>
      )
    }

به جای آن تک تک اعضای این آرایه را با یک تابع دلخواه که به map می دهیم از درون تابع بیرون می کشیم:

{this.state.persons.map(person => {
            
   })}

درون تابع map از یک arrow function استفاده کرده ام (از نوع anonymous). قبلا در مورد arrow function ها صحبت کرده بودیم (ر.ک به مروری بر ES6). البته شما می توانیم هر نامی به جای person را برای این تابع انتخاب کنید (به سلیقه خودتان بستگی دارد).

حالا باید کدهای این تابع را بنویسیم:

{this.state.persons.map(person => {
            return <Person
            name={person.name}
            age={person.age} />
          })}

تنها کاری که باید انجام دهیم، این است که در این تابع کدها را به صورت JSX برگردانیم و با استفاده از چند خط کد ساده همین کار را کرده ایم. من کدها را در چند خط شکسته ام که خواناتر باشند شما می توانید آن ها را در یک خط بنویسید.

حالا می توانیم کدهای دستی را حذف کنیم:

    if (this.state.showPersons) {
      persons = (
        <div>
          {this.state.persons.map(person => {
            return <Person
              name={person.name}
              age={person.age} />
          })}
        </div>
      )
    }

اگر در حال حاضر به مرورگر بروید متوجه می شوید که کد ما کار می کند اما در console با خطا مواجه می شویم. دلیل خطاها کامل نبودن کد ما است. در قسمت بعد باید کدها را تکمیل کنیم چرا که در حال حاضر فقط یک لیست را نمایش میدهیم و تمام event-listener ها را حذف کرده ایم.

خلاصه استفاده از map
خلاصه استفاده از map

سعی کنید قبل از مطالعه قسمت بعد، منطق این کدها را تمرین کنید.

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

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