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) {
state = [...state, item];
}

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

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

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.