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');
}
Provider'ları static final değişkenler olarak oluşturmak mümkündür, ancak kod üretici tarafından desteklenmez.