Skip to main content

State & Provider

A provider in riverpod_craft provides data. You annotate a function or class with @provider, and the code generator creates everything you need — a Riverpod provider, notifier, and a clean API to access it.

What is a Provider?

A provider is auto-triggered — it runs automatically when something uses it. You just write the logic:


String myName(Ref ref) => 'John';

Now you can use it anywhere:

final name = ref.myNameProvider.watch(); // 'John'

Functional Provider

A single function annotated with @provider. Use this for simple values:


String appTitle(Ref ref) => 'My Notes App';

int maxItemsPerPage(Ref ref) => 20;

These are read-only — they provide a value, and that's it.

Class Provider

A class annotated with @provider with a create() method. Use this when you need custom methods or business logic:


class Cart extends _$Cart {

List<CartItem> create() => [];

void addItem(CartItem item) {
setState([...state, item]);
}

void removeItem(String itemId) {
setState(state.where((item) => item.id != itemId).toList());
}

void clear() => setState([]);
}

The generated code exposes your methods directly:

ref.cartProvider.addItem(item);
ref.cartProvider.removeItem(id: '123');
ref.cartProvider.clear();

final items = ref.cartProvider.watch();

Use in widgets

class CartPage extends ConsumerWidget {

Widget build(BuildContext context, WidgetRef ref) {
final items = ref.cartProvider.watch();

return Column(
children: [
...items.map((item) => ListTile(
title: Text(item.name),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () => ref.cartProvider.removeItem(item.id),
),
)),
FilledButton(
onPressed: () => ref.cartProvider.clear(),
child: const Text('Clear Cart'),
),
],
);
}
}

Simple State @settable

Add @settable to a functional provider to make the state updatable. Use this for simple state like filters, toggles, and search queries:



NoteCategory categoryFilter(Ref ref) => NoteCategory.all;


String searchQuery(Ref ref) => '';


bool isDarkMode(Ref ref) => false;

Now you can update the value with setState():

// Update
ref.categoryFilterProvider.setState(NoteCategory.work);
ref.searchQueryProvider.setState('meeting notes');
ref.isDarkModeProvider.setState(true);

// Watch — reacts automatically to changes
final category = ref.categoryFilterProvider.watch();
info

@settable only works on functional providers. Class-based providers use their own methods to update state.

When to Use Each Style

FunctionalFunctional + @settableClass Provider
WhatRead-only valueSimple updatable stateState + custom logic
ExamplesApp title, config values, computed dataFilters, toggles, search query, theme modeCart, form state, counters with logic
Update withCannot updatesetState(newValue)Custom methods like addItem(), clear()

Next

Now that you know how to manage local state, learn how to fetch data from APIs:

Fetch Data

To perform side effects (submit forms, delete items, API mutations), see:

Side Effect (Command)

Commands for data fetching too

Commands aren't just for mutations. You can use @command to fetch data that requires user input — like submitting a phone number to look up user info, or filling a form to query search results. See Command for details.