پرسش

چرا در React (ری اکت) this.setState یک فانکشن نیست؟

React: this.setState is not a function

من دارم از ری‌اکت استفاده می‌کنم و وقتی سعی می‌کنم از this.setState استفاده کنم، با ارور this.setState is not a function مواجه می‌شم. کدی که دارم استفاده می‌کنم به این شکل هست:

constructor(props) {
    super(props);
    this.state = {
          someKey: 'someValue'
    };
   this.handleClick = this.handleClick.bind(this);
    }
   handleClick() {
     this.setState({ someKey: 'newValue' });
   }
  render() {
     return (
         <button onClick={this.handleClick}>Click me</button>
      );
}

مشکل چیه و چطور می‌تونم این ارور رو حل کنم؟

پاسخ
محمدامین سعیدی راد
بیوگرافی محمدامین سعیدی راد

این اروری که می‌گیری، معمولاً به این دلیل اتفاق میفته که this به درستی به فانکشن handleClick بایند (bind) نشده. در جاوااسکریپت، this به صورت دینامیک مشخص می‌شه، یعنی اینکه بستگی به جایی که فانکشن صدا زده می‌شه، داره. اگه this به درستی بایند نشده باشه، وقتی سعی می‌کنی از this.setState استفاده کنی، this به جای اینکه به کامپوننت شما اشاره کنه، به یه چیز دیگه اشاره می‌کنه و در نتیجه this.setState فانکشن نخواهد بود.
حالا برای اینکه این مشکل رو حل کنی، چند تا روش داری:

  • بایند کردن فانکشن در کانستراکتور: همونطور که توی کد خودت هم انجام دادی، بهترین و استانداردترین راه اینه که فانکشن رو داخل کانستراکتور بایند کنی. اما اگه این کار رو نکردی، به این شکل عمل کن:
constructor(props) {
  super(props);
  this.state = {
     someKey: 'someValue'
   };
    this.handleClick = this.handleClick.bind(this);
}
  • استفاده از arrow function در تعریف فانکشن: روش دیگه‌ای که خیلی رایج شده، استفاده از arrow function هست. arrow function ها به صورت خودکار this رو به context فعلی بایند می‌کنن:
handleClick = () => {
       this.setState({ someKey: 'newValue' });
}

با این روش دیگه نیازی نیست که توی کانستراکتور بایند کنی و کد هم یه مقدار تمیزتر می‌شه.

  • استفاده از arrow function در JSX: شما می‌تونی فانکشن رو مستقیماً توی JSX به صورت arrow function صدا بزنی:
render() {
  return (
    <button onClick={() => this.handleClick()}>Click me</button>
  );
}

البته این روش باعث می‌شه هر بار که کامپوننت رندر می‌شه، یه فانکشن جدید ساخته بشه که از نظر کارایی (performance) ممکنه بهینه نباشه، ولی در پروژه‌های کوچیک یا جاهایی که performance اهمیت زیادی نداره، قابل استفاده است.

این روش‌ها کمک می‌کنه که this به درستی بایند بشه و دیگه اون ارور رو نگیری.

پاسخ: 1403/06/05
آخرین آپدیت: 1403/08/10