0%
إدارة الحالة

إدارة الحالة

تحديد المكان الذي يعيش فيه المعطى، ومن ينبغي إخطاره عند تغيّره

15-20 دقيقة

إدارة الحالة

يحظى هذا الموضوع بسمعة سيئة، تغذّيها كثرة الحلول المتنافسة والنقاشات التي تثيرها. ينبغي تبديد هذه السمعة منذ البداية: المشكلة الحقيقية ليست الاختيار بين ثلاث مكتبات، بل الإجابة عن سؤال بسيط لكل معطًى في تطبيقك. من يحتاج إليه؟

خانة الاختيار لا تهمّ إلا السطر الذي يحتويها: setState يكفي، وأي حل آخر سيكون تعقيدًا بلا مبرر. أما سلة المشتريات فتقرأها قائمة المنتجات، وشارة الشريط العلوي، وشاشة الطلب، وشاشة الدفع — أربعة مواضع لا يجمعها أي سلف مشترك قريب. تمرير السلة من مُنشئ إلى آخر عبر ست طبقات من الودجات يعمل، لكنه ينتج شيفرة يمسّ فيها أي تغيير صغير عشرة ملفات. لهذه الظاهرة اسم، هو تمرير الخصائص عبر الطبقات (prop drilling)، وهي — لا setState — ما يبرر وجود Provider.

يتبع هذا الدرس هذا التسلسل بالضبط: setState وما يجيده، ثم الجدار الذي يصطدم به، ثم InheritedWidget وهو آلية الإطار لتجاوزه، ثم Provider الذي يغلّفه في صورة عملية للاستخدام اليومي. وفي النهاية سيكون بين يديك معيار للقرار، لا مجرد تفضيل.

setState: ما يجيده

لنبدأ بالحالة المشروعة: معطًى يستخدمه ودجت واحد فقط، ويزول بزواله:

import 'package:flutter/material.dart';

class CarteDepliable extends StatefulWidget {
  final String titre;
  final String contenu;

  const CarteDepliable({
    super.key,
    required this.titre,
    required this.contenu,
  });

  @override
  State<CarteDepliable> createState() => _CarteDepliableState();
}

class _CarteDepliableState extends State<CarteDepliable> {
  bool _ouvert = false;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        children: [
          ListTile(
            title: Text(widget.titre),
            trailing: Icon(_ouvert ? Icons.expand_less : Icons.expand_more),
            onTap: () => setState(() => _ouvert = !_ouvert),
          ),
          // لا شيء آخر في التطبيق يحتاج إلى معرفة
          // ما إذا كانت هذه البطاقة مفتوحة. الحالة في مكانها الصحيح.
          if (_ouvert)
            Padding(
              padding: const EdgeInsets.all(16),
              child: Text(widget.contenu),
            ),
        ],
      ),
    );
  }
}

التعليقات

التعليقات مدعومة عبر GitHub Discussions

سجّل الدخول باستخدام GitHub للمشاركة في النقاش

تم نسخ الرابط!