اذهب إلى المحتوى
  • 0

لا يتم تحديث الحالة عند استخدام setInterval في مكون React

Adam Ebrahim

السؤال

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

import React from 'react'

function Time() {
  // القيمة هنا لا تزيد عن 1
  const [clock, setClock] = React.useState(0);
  
  React.useEffect(() => {
    const timer = window.setInterval(() => {
      // أعتقد أن هنا يوجد خطأ ما
      setClock(clock + 1);
    }, 1000);
    
    return () => {
      window.clearInterval(timer);
    };
  }, []);

  return (
    <div>Seconds: {clock}</div>
  );
}

ReactDOM.render(<Time />, document.getElementById('app'));

تأكدت من أن useEffect ستعمل مرة واحدة من خلال إضافة مصوفة فارغة كعامل ثاني لهذا الخطاف، لكن يبدو أن هذا لا يحل المشكلة.

رابط هذا التعليق
شارك على الشبكات الإجتماعية

Recommended Posts

  • 0

لننظر إلى السطر التالي:

setClock(clock + 1);

من أين تأتي clock؟ من خارج التابع الممرر إلى useEffect وبالتالي لدينا closure وقيمة الـclock عند استدعاء التابع داخل useEffect هي 0 لذا التعليمة السابقة مكافئة للتالية:

setClock(0 + 1); // => setClock(1)

هذا يحصل كل ثانية ولكن لا معنى لذلك ﻷنك تضع قيمة ثابتة.

لحل المشكلة نستخدم نسخة setClock التي تمرر لها تابعاً هكذا:

setClock(clock => clock + 1);

بهذه الطريقة تحل المشكلة بإذن الله.

طبعاً هناك طريقة ثانية وهي تمرير clock ضمن dependencies array ولكن تلك الطريقة ستقوم بعمل clearInterval ثم setInterval بشكل متكرر مما يؤذي اﻷداء لذلك لم نتبعها.

رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

جميل جدا أستخدامك لل useEffect هنا كما أنك راعيت عملية ال clean عند ازالة الكمبوننت باستعمالك clearInterval

الكود داخل ال useEffect  يعمل في أول مرة فقط لانك حددت قوسين المصفوفه ومعناه أن تعمل مرة واحدة فقط 

وبالتالي سوف يتغير الرقم من 0 الى 1 وبعد ذلك لن يعمل الكود مرة أخرى.

ولكنك تريد للكود داخل ال useEffect  ان يتم تنفيذه في كل مرة تتغير قيمة المتغير clock حتى يعمل عداد الساعه 

وبالتالي لابد من اضافة المتغير clock داخل قوسي المصفوفه

ففائدة القوسين هنا أن نخبر ال useEffect  ان ينفذ مابداخلها طالما مابداخل القوسين يتغيران

فيصبح الكود في النهايه كالاتي 

import React from 'react'

function Time() {
  // القيمة هنا لا تزيد عن 1
  const [clock, setClock] = React.useState(0);
  
  React.useEffect(() => {
    const timer = window.setInterval(() => {
      // أعتقد أن هنا يوجد خطأ ما
      setClock(clock + 1);
    }, 1000);
    
    return () => {
      window.clearInterval(timer);
    };
  }, [clock]);

  return (
    <div>Seconds: {clock}</div>
  );
}

ReactDOM.render(<Time />, document.getElementById('app'));

ولكن هذا الحل يضر بالاداء الخاص بالتطبيق كوننا نقوم بإنشاء timer جديد في كل مره 
ولذا ف الحل الامثل ان نستخدم ال functional setClock فيصير الكود كالاتي

import React from 'react'

function Time() {
  // القيمة هنا لا تزيد عن 1
  const [clock, setClock] = React.useState(0);
  
  React.useEffect(() => {
    const timer = window.setInterval(() => {
      // أعتقد أن هنا يوجد خطأ ما
      setClock(clock => clock + 1);
    }, 1000);
    
    return () => {
      window.clearInterval(timer);
    };
  }, [clock]);

  return (
    <div>Seconds: {clock}</div>
  );
}

ReactDOM.render(<Time />, document.getElementById('app'));

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...