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

السؤال

نشر

لقد تعلمت React خلال الأيام القليلة الماضية، وألقيت نظرة على بعض البرامج التعليمية والتفسيرات المتعلقة بالطرق المختلفة التي يمكنك من خلالها كتابة عناصر مختلفة. ومع ذلك، هناك واحد لم أفهمها بشكل جيد - وظيفة setState لتحديث حالة مكون React.

على سبيل المثال ، لنفترض أن لدي صنف كما يلي، ويقوم هذا الصنف بإستخدام API لجلب الأسماء من السيرفر بإستخدام fetch:

class Person extends React.Component {
    constructor() {
        super()
        state = {
            firends: []
        }
    }

   componentDidMount() {
      // هنا ستكون fetch و setState
   }

    render() {
       return {
          <div className="container">
             {this.state.firends}
          </div>
       }
    }
}

نظرًا لأنني أجريت عملية الجلب والتعيين وreturn لهذه الدالة - سأقوم بعد ذلك بتحديث friends: []  بالنتائج القادمة من الـ API. سؤالي حول الطرق المختلفة التي رأيتها فيما يتعلق بكيفية تحديث حالة المكون friends، حيث رأيت طريقتين مختلفتين لعمل نفس الشيء:

  1. الطريقة الأولى سهلة للغاية وواضحة أيضًا
    this.setState({firends: names})

     

  2. أما الطريقة الأخرى فتبدو أكثر تعقيدًا بدون سبب ويتم وصفها بأنها أكثر أمانًا:
    this.setState(prevState => ({
       friends: prevState.friends.concat(names)
    }))

    هل يمكن لشخص ما أن يشرح مزايا استخدام كل طريقة منهما؟ وما عيوب كلًا منهما؟

Recommended Posts

  • 1
نشر

اذا ما نظرنا الى الطريقة الاولى سنجد الاتي: 
نحن نقوم بتخزين النتائج القادمه من ال API مباشرة الى friends وكل النتائج السابقه ستحذف 

أما الطريقة الثانيه فنحن نضيف النتائج الجديده الى القديمه 

ولكن مال الفرق الجوهري حقا بين الاسلوبين

الاسلوب الثاني اذا مالاحظت فإنه يكون لديك وصول كامل الى ال state الحاليه   قبل ان تقوم بأي تعديل علىيها فيمكنك هنا ان تفحص مثلا اذا كان هناك اسم مكرر في قائمة الاصدقاء ف تحذفه أو تقوم بأي عمليات أخرى على الاستيت القديمه والقيمه الجديده ومن ثم تخزن القيم النهائيه في ال state وكل ذلك عكس الطريقة الاولى حيث لا يمكنك عمل ذلك.

وهناك سبب أخر لوجود مثل هذا التكنيك رقم 2 وهو أن ريأكت تقوم بعمل مايسمى ب batching لل setState بمعنى اذا تم استدعاء setState أكثر من مره على التوالي كالاتي مثلا:

state = {
   count: 0
}
updateCount = () => {
    this.setState({ count: this.state.count + 1});
    this.setState({ count: this.state.count + 1});
    this.setState({ count: this.state.count + 1});
    this.setState({ count: this.state.count + 1});
}

سوف يتم تنفيذ الأخيرة فقط بمعنى ان ال count في النهايه سوف يزيد بمقدار واحد فقط وتصبح قيمة ال count تساوي واحد

وللتغلب على هذا نستخدم الاسلوب الثاني حيث يكون لدينا الوصول على ال state قبل التعديل عليها ونضيف عليها واحد كالاتي: 
 

updateCount = () => {
    this.setState(prevstate => ({ count: prevstate.count + 1}));
    this.setState(prevstate => ({ count: prevstate.count + 1}));
    this.setState(prevstate => ({ count: prevstate.count + 1}));
    this.setState(prevstate => ({ count: prevstate.count + 1}));
}

فتصبح قيمة ال count  في النهايه تساوي 4.

 

  • 1
نشر

الأمر سهل وبسيط فقط عندما تفهم احتياجاتك في الشيفرة التي تود كتابتها .

يمكن صياغة الأمر الى استخدامين الأول في حالة انك لا تعتمد على الstate القديم في اجراء التغييرات وهذا مثال بسيط

export default function App() {
  const [state, setState] = useState('some data');

  const handleChange = () => {
    setState('other data');
  };

  return <div>.....</div>;
}

و هذا مثال أخر 

export default function App() {
  const [state, setState] = useState({
    username: '',
    password: '',
  });

  const handleChange = (e) => {
    setState({
      ...state,
      [e.target.name]: e.target.value,
    });
  };

  return <div>.....</div>;
}

لكن في حالة ما اذا اردت تغيير ال state بالاعتماد على ال state القديم فحينها يجب عليك استخدام callback 

export default function App() {
  const [state, setState] = useState(0);

  const handleChange = (e) => {
    function increment() {
      setState((prevState) => prevState + 1);
    }
  };

  return <div>.....</div>;
}

 

  • 0
نشر
  1. عندما تستخدم الطريقة الأولى سيتم إزالة جميع النتائج الموجودة في ال state وسيتم وضع النتائج الجديدة دائماً.
  2. أما إذا كنت تريد الحفاظ على النتائج القديمة مثلاً تستخدم الطريقة الثانية حتى لا تمسح القديم 

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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.

  • إعلانات

  • تابعنا على



×
×
  • أضف...