Ana içeriğe atla

YAPIN/YAPMAYIN

Kodunuzun iyi bir sürdürülebilirliğe sahip olmasını sağlamak için, Riverpod kullanırken izlemeniz gereken iyi uygulamaların bir listesi aşağıdadır.

Bu liste kapsamlı değildir ve değişebilir.
Önerileriniz varsa çekinmeden bir issue açın.

Listedeki maddeler belirli bir sıraya göre dizilmemiştir.

Bu önerilerin önemli bir kısmı riverpod_lint ile denetlenebilir. Kurulum talimatları için Başlarken sayfasına bakın.

Provider'ları bir widget içinde başlatmaktan KAÇININ

Provider'lar kendi kendilerini başlatmalıdır.
Widget gibi harici bir öğe tarafından başlatılmamalıdırlar.

Buna uymamak yarış koşullarına (race condition) ve beklenmedik davranışlara yol açabilir.

YAPMAYIN

class WidgetState extends State<MyWidget> {

void initState() {
super.initState();
// Kötü: provider kendi kendini başlatmalı
ref.read(provider).init();
}
}

DEĞERLENDİRİN

Bu sorunun "herkese uyan" tek bir çözümü yoktur.
Başlatma mantığınız provider'ın dışındaki etkenlere bağlıysa, böyle bir mantığı koymak için doğru yer çoğu zaman yönlendirmeyi tetikleyen bir butonun onPressed metodudur:

ElevatedButton(
onPressed: () {
ref.read(provider).init();
Navigator.of(context).push(...);
},
child: Text('Navigate'),
)

Geçici (ephemeral) durum için provider kullanmaktan KAÇININ.

Provider'lar paylaşılan iş durumu için tasarlanmıştır. Şunlar gibi geçici durumlar için kullanılmak üzere düşünülmemişlerdir:

  • O anda seçili olan öğe.
  • Form durumu. Çünkü formdan çıkıp yeniden girmek tipik olarak form durumunu sıfırlamalıdır. Çok sayfalı formlarda geri butonuna basmak da buna dahildir.
  • Animasyonlar.
  • Genel olarak Flutter'ın bir "controller" ile ele aldığı her şey (örneğin TextEditingController)

Yerel widget durumunu yönetmenin bir yolunu arıyorsanız, bunun yerine flutter_hooks kullanmayı düşünün.

Bunun önerilmemesinin bir nedeni, böyle bir durumun çoğu zaman bir rotaya özgü olmasıdır.
Buna uymamak, yeni bir sayfanın önceki sayfanın durumunu geçersiz kılması nedeniyle uygulamanızın geri butonunu bozabilir.

Örneğin, o anda seçili olan book değerini bir provider'da sakladığımızı varsayalım:

final selectedBookProvider = StateProvider<String?>((ref) => null);

Karşılaşabileceğimiz bir zorluk şudur: gezinme geçmişi şöyle görünebilir:

/books
/books/42
/books/21

Bu senaryoda geri butonuna bastığımızda /books/42ye dönmeyi bekleriz. Ancak seçili kitabı saklamak için selectedBookProvider kullanacak olsaydık, seçili ID önceki değerine sıfırlanmaz ve /books/21i görmeye devam ederdik.

Bir provider'ın başlatılması sırasında yan etki gerçekleştirMEYİN

Provider'lar genel olarak bir "okuma" işlemini temsil etmek için kullanılmalıdır. Bir formu göndermek gibi "yazma" işlemleri için kullanmamalısınız.

Provider'ları bu tür işlemler için kullanmak, önceki bir yan etki gerçekleştirilmişse yenisinin atlanması gibi beklenmedik davranışlara yol açabilir.

Bir yan etkinin yükleniyor/hata durumlarını ele almanın bir yolunu arıyorsanız,

Mutation'lar (deneysel) sayfasına bakın.

YAPMAYIN:

final submitProvider = FutureProvider((ref) async {
final formState = ref.watch(formState);

// Kötü: Provider'lar "yazma" işlemleri için kullanılmamalıdır.
return http.post('https://my-api.com', body: formState.toJson());
});

ref.watch/read/listen (ve benzeri API'leri) statik olarak bilinen provider'larla kullanmayı TERCİH EDİN

Riverpod, lint kurallarının (riverpod_lint aracılığıyla) etkinleştirilmesini kuvvetle önerir.
Ancak lint'lerin etkili olabilmesi için kodunuzun statik olarak analiz edilebilir biçimde yazılması gerekir.

Buna uymamak hataları fark etmeyi zorlaştırabilir veya lint'lerde yanlış pozitiflere yol açabilir.

Yapın:

final provider = Provider((ref) => 42);

...

// Provider statik olarak bilindiği için sorun yok
ref.watch(provider);

Yapmayın:

class Example extends ConsumerWidget {
Example({required this.provider});
final Provider<int> provider;


Widget build(context, ref) {
// Kötü, çünkü statik analiz `provider`ın ne olduğunu bilemez
ref.watch(provider);
}
}

Provider'ları dinamik olarak oluşturmaktan KAÇININ

Provider'lar yalnızca üst düzey (top-level) final değişkenler olmalıdır.

Yapın:

final provider = Provider<String>((ref) => 'Hello world');

Yapmayın:

class Example {
// Desteklenmeyen kullanım. Bellek sızıntılarına ve beklenmedik davranışlara yol açabilir.
final provider = Provider<String>((ref) => 'Hello world');
}
bilgi

Provider'ları static final değişkenler olarak oluşturmak mümkündür, ancak kod üretici tarafından desteklenmez.