riverpod_essentials 0.0.2 copy "riverpod_essentials: ^0.0.2" to clipboard
riverpod_essentials: ^0.0.2 copied to clipboard

The Essential Providers for Riverpod.

riverpod_essentials #

A small collection of practical Riverpod providers for common state patterns:

  • valueProvider: generic simple state provider (set, reset)
  • nullableValueProvider: nullable state provider (set, reset)
  • countdownProvider: countdown state with start/stop controls
  • debounceProvider: debounce async values before they resolve

These providers are generated with riverpod_generator and work well for small, reusable state interactions such as counters, search keywords, delayed inputs, and simple local UI state.

Features #

  • Simple countdown state with restart and cancel support
  • Debounced async provider for delayed value emission
  • Generic mutable value provider with set and reset
  • Built-in convenience methods for bool and int states
  • Optional alwaysNotify support when you want to notify listeners even if the assigned value is unchanged

Getting started #

Add the package to your pubspec.yaml:

dependencies:
    riverpod_essentials: ^0.0.2

Then run:

flutter pub get

Providers #

valueProvider #

valueProvider is a generic simple state provider keyed by id. It supports set(), reset(), and typed convenience methods for bool and int. Use alwaysNotify: true if you want to emit updates even when assigning the same value:

nullableValueProvider #

nullableValueProvider works like valueProvider, but its state can be null. This is useful for optional form values, filters, and temporary selections. For nullable int or bool values, the convenience methods still work:

  • toggle() treats null as false
  • increase() and decrease() treat null as 0

countdownProvider #

countdownProvider stores the remaining countdown value as an int. Call start() to begin a countdown, and stop() to cancel it.

Notes:

  • The initial value is 0
  • Calling start() again restarts the countdown
  • The timer is automatically cancelled when the provider is disposed

debounceProvider #

debounceProvider delays returning a value until the debounce duration has elapsed. This is useful for search, filtering, and text input handling.

If the provider is disposed before the debounce duration ends, the pending future is cancelled with an error.

When to use #

Choose a provider based on the state pattern you need:

  • Use valueProvider for simple mutable state with a fixed non-null value
  • Use nullableValueProvider for optional mutable state
  • Use countdownProvider for timers, resend buttons, and cooldown UI
  • Use debounceProvider for search or delayed request parameters

Example #

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_essentials/riverpod_essentials.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ProviderScope(child: MaterialApp(home: const HomePage()));
  }
}

final _countProvider = valueProvider<int>('counter', initialValue: 0);
final _countdownProvider = countdownProvider('countdown');
final _textProvider = valueProvider<String>('text', initialValue: '');

class HomePage extends ConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(_countProvider);
    final countdown = ref.watch(_countdownProvider);
    final isCountdownStopped = countdown == 0;
    final text = ref.watch(_textProvider);
    final debouncedText = ref.watch(debounceProvider(text)).value;
    return Scaffold(
      appBar: AppBar(title: Text('Riverpod Essentials Example')),
      body: ListView(
        children: [
          ListTile(
            title: Text('Count: $count'),
            trailing: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                IconButton(
                  onPressed: () => ref.read(_countProvider.notifier).increase(),
                  icon: Icon(Icons.add),
                ),
                IconButton(
                  onPressed: () => ref.read(_countProvider.notifier).reset(),
                  icon: Icon(Icons.restart_alt),
                ),
              ],
            ),
          ),
          ListTile(
            title: Text('Countdown: $countdown'),
            trailing: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                FilledButton(
                  onPressed: () => isCountdownStopped
                      ? ref.read(_countdownProvider.notifier).start(10)
                      : ref.read(_countdownProvider.notifier).stop(),
                  child: Text(isCountdownStopped ? 'Start' : 'Stop'),
                ),
              ],
            ),
          ),
          ListTile(
            title: TextField(
              decoration: InputDecoration(hintText: 'Please input'),
              onChanged: (value) => ref.read(_textProvider.notifier).set(value),
            ),
            trailing: Text(debouncedText == null ? 'Typing...' : 'Ready to Go'),
          ),
        ],
      ),
    );
  }
}

Repository #