หลักการออกแบบเบื้องหลัง miniriverpod.

แพ็กเกจนี้จงใจลดทอนฟีเจอร์เพื่อให้พฤติกรรมชัดเจน: เอกลักษณ์ของ provider ด้วย args, การ inject แบบ scoped และ semantics ของการ dispose ที่คาดเดาได้.

สิ่งที่เปลี่ยนไปจาก Riverpod

แทนที่จะใช้ generated family classes และ channels ของ notifier แบบ implicit, miniriverpod เลือก subclass + args + explicit invoke.

Provider identity

runtimeType + args hash

family alternative

สืบทอด Provider / AsyncProvider และส่ง super.args((...))

DI fallback

Scope<T>.required + overrideWithValue

ทำไมสิ่งนี้จึงสำคัญ

คุณสามารถใช้ constructor ของ Dart ปกติเพื่อให้เหตุผลเกี่ยวกับ equality และ overrides ได้ ซึ่งทำให้การ debug และการทดสอบตรงไปตรงมา.

การระบุ Provider ด้วย args

args กำหนดคีย์ของ provider ดังนั้น args ที่เท่ากันหมายถึง cache entry เดียวกันภายใน ProviderContainer.

Identity rule

ผลลัพธ์เชิงปฏิบัติ

- ไม่จำเป็นต้องมี family type แยกต่างหาก.
- การ override ราย argument ทำได้โดยการสร้าง provider instances.
- ควรรักษา args ให้คงที่และไม่เปลี่ยนแปลงเพื่อ caching ที่คาดเดาได้.

ตัวอย่าง: provider แบบ family + Scope สำรอง

ใช้ argument ของ constructor เป็นตัวระบุ และ inject instance สำรองผ่าน Scope.

class ProductProvider extends AsyncProvider<List<Product>> {
  ProductProvider({this.search = ''}) : super.args((search,));
  final String search;

  static final fallback = Scope<ProductProvider>.required('product.fallback');

  @override
  FutureOr<List<Product>> build(ref) async {
    final api = ref.watch(productsApiProvider);
    return api.search(q: search);
  }
}

// Inject
ProviderScope(
  overrides: [
    ProductProvider.fallback.overrideWithValue(ProductProvider(search: 'jeans')),
  ],
  child: const App(),
);
Scope ทำให้การเชื่อมโยง dependency ชัดเจนและเป็นมิตรต่อการทดสอบ.
overrideWithValue ทำงานต่อ provider instance แต่ละตัว รวมถึง instances ที่อิง args.
พฤติกรรม autoDispose ไม่เปลี่ยนเมื่อใช้ subclass + args.

ขั้นตอนถัดไป

Providers และการอ่าน

ดูรูปแบบที่เป็นรูปธรรมสำหรับ watch/read/listen และ AsyncProvider.future.

เปิด Providers

มิวเทชัน

ใช้งานการอัปเดตสถานะด้วย mutation tokens, mutate และ ref.invoke.

เปิดมิวเทชัน