labZero:~$ cd ./notes / note-flutter-setstate-re...
setState صغيرة في المكان الخطأ تُعيد رسم صفحة كاملة — وتأثيرها غير مرئي بالعين.
قائمة بها 80 بطاقة كانت تتحرك بسلاسة في التطوير وتتقطع على أجهزة ضعيفة — تتبّعت المشكلة لـ setState في widget أعلى الشجرة.
في تطبيق عرض منتجات بـ Flutter، كانت الواجهة سلسة تماماً على Pixel 8 وتتقطع على أجهزة الفئة المتوسطة. المنطق بسيط: قائمة 80 بطاقة تُعرض في ListView.builder. لا شبكة، لا صور ثقيلة، لا computed data. الكود يبدو نظيفاً.
الجوهر: فتحت Flutter DevTools وشغّلت Performance tab. كل نقرة على زر تصفية في أعلى الصفحة كانت تُعيد بناء الشجرة كاملاً — 80 بطاقة + header + bottom bar في كل ضغطة. السبب: setState كانت في الـ StatefulWidget الجذري الذي يحمل كل الصفحة. تغيير filterActive = true يُعيد بناء كل child حتى البطاقات التي لا يمسّها التصفية.
الحل: استخرجت state التصفية إلى ValueNotifier وأحطت فقط الـ widget المعنية بـ ValueListenableBuilder. الـ 80 بطاقة لا تُلمس عند تغيير الفلتر.
final _filter = ValueNotifier<FilterType>(FilterType.all);
ValueListenableBuilder<FilterType>(
valueListenable: _filter,
builder: (_, filter, __) => FilterBar(active: filter),
),
ما حملته من هذا: setState ليست مجانية حين تكون في أعلى الشجرة — التكلفة تتناسب مع عمق الـ widget tree تحتها. قبل استخدامها في أي widget لديه children، أتحقق أولاً هل يمكن عزل التغيير في فرع أضيق.