Skip to content

ref.exists()

ref.exists() checks whether a provider has already been created inside the current ProviderContainer without creating or initializing it.


What is it?

ref.exists() allows you to determine whether a provider already has an active state.

Unlike ref.watch(), ref.read(), or ref.refresh(), calling ref.exists() does not create the provider if it doesn't already exist.

It simply answers the question:

"Has this provider already been initialized?"

This is useful when you want to inspect the state of the provider lifecycle without triggering initialization.


Why does it exist?

Normally, accessing a provider causes Riverpod to initialize it if it hasn't been created yet.

Sometimes that's not desirable.

For example:

  • Avoid creating an expensive provider unnecessarily.
  • Check whether cached data already exists.
  • Conditionally invalidate a provider.
  • Debug provider lifecycles.
  • Skip cleanup for providers that were never initialized.

ref.exists() lets you perform these checks safely.


Availability

✅ Available in all provider types.

It can be used inside:

  • Provider
  • FutureProvider
  • StreamProvider
  • Notifier
  • AsyncNotifier
  • StreamNotifier

It can also be used through a ProviderContainer.


Syntax

Checking if a Provider Exists

final exists = ref.exists(userProvider);

Explanation:

  • Returns true if userProvider has already been created.
  • Returns false if it has never been initialized.

Conditional Invalidation

if (ref.exists(userProvider)) {
  ref.invalidate(userProvider);
}

Explanation:

  • Avoids invalidating a provider that doesn't exist.
  • Prevents unnecessary work.

Conditional Refresh

if (ref.exists(productsProvider)) {
  ref.refresh(productsProvider);
}

Explanation:

  • Refreshes only active providers.
  • Doesn't initialize inactive ones.

Return Value

ref.exists() returns a bool.

Value Meaning
true Provider has already been created
false Provider has not been initialized

Execution Flow

Provider Created?
      │
 ┌────┴────┐
 │         │
Yes       No
 │         │
 ▼         ▼
true     false

Unlike read() or watch(), no provider is created during this check.


Mental Model

Think of ref.exists() as checking whether a room is occupied.

ProviderContainer
        │
        ▼
Does Provider Exist?
        │
   ┌────┴────┐
   │         │
Yes         No
   │         │
   ▼         ▼
true      false

It looks without opening the door.


Examples

Simple Example

if (ref.exists(counterProvider)) {
  print('Counter is initialized');
}

Explanation:

  • Checks whether the provider already exists.
  • Doesn't create the provider.

Avoid Unnecessary Refresh

if (ref.exists(newsProvider)) {
  ref.refresh(newsProvider);
}

Explanation:

  • Refreshes only if the provider is active.
  • Avoids creating a new provider.

Debugging

debugPrint(
  'User provider exists: ${ref.exists(userProvider)}',
);

Explanation:

  • Helps inspect provider lifecycles during development.

Real-World Example

Future<void> logout() async {
  await authRepository.logout();

  if (ref.exists(profileProvider)) {
    ref.invalidate(profileProvider);
  }
}

Explanation:

  • Clears the profile only if it has already been created.
  • Avoids unnecessary provider initialization.

When to Use

Use ref.exists() when:

  • Checking whether a provider has been initialized.
  • Conditionally refreshing providers.
  • Conditionally invalidating providers.
  • Debugging provider lifecycles.
  • Avoiding unnecessary provider creation.

When NOT to Use

Avoid ref.exists() when:

  • You need the provider's value.
  • You want to initialize the provider.
  • You need reactive updates.

Instead, use:

  • ref.watch()
  • ref.read()
  • ref.refresh()

Best Practices

  • Use exists() only when lifecycle information is needed.
  • Don't replace read() or watch() with exists().
  • Combine with invalidate() or refresh() when appropriate.
  • Keep lifecycle checks simple.
  • Avoid overusing it in application logic.

Common Mistakes

1. Expecting exists() to Create a Provider

❌ Wrong

final exists = ref.exists(userProvider);

// Expecting userProvider to be initialized

Why it's wrong:

  • exists() only checks for existence.
  • It never creates the provider.

✔ Correct

final user = ref.read(userProvider);

2. Using exists() Instead of read()

❌ Wrong

if (ref.exists(counterProvider)) {
  // Need the counter value
}

Why it's wrong:

  • exists() doesn't return the provider's value.

✔ Correct

final counter = ref.read(counterProvider);

3. Overusing exists()

❌ Wrong

if (ref.exists(provider)) {
  ref.read(provider);
}

Why it's wrong:

  • read() will initialize the provider if necessary.
  • The existence check is often redundant.

✔ Correct

Use read() directly unless you specifically need lifecycle information.


4. Assuming exists() Means the Provider Is Active

❌ Wrong

if (ref.exists(provider)) {
  // Provider must have active listeners
}

Why it's wrong:

  • A provider can exist without currently being listened to.
  • exists() only indicates that it has been initialized.

✔ Correct

Treat exists() as an initialization check, not a listener check.


ref.exists() vs ref.read()

Feature ref.exists() ref.read()
Returns provider value
Initializes provider ✅ (if needed)
Returns bool
Registers dependency
Best for lifecycle checks

  • ref.read()
  • ref.watch()
  • ref.invalidate()
  • ref.refresh()
  • ProviderContainer

Summary

ref.exists() checks whether a provider has already been initialized without creating it. It is useful for lifecycle inspection, conditional invalidation, debugging, and avoiding unnecessary provider creation. Unlike ref.read() or ref.watch(), it never initializes the provider or returns its value—it simply reports whether the provider currently exists in the ProviderContainer.