Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref.read() gets previous state, instead of the same value as next from ref.listen() #3879

Open
JifScharp opened this issue Dec 20, 2024 · 2 comments
Assignees
Labels
bug Something isn't working question Further information is requested

Comments

@JifScharp
Copy link

JifScharp commented Dec 20, 2024

Describe the bug
I am listening for a state change, and when it occurs triggering some separate logic to do some more complex checks on the state. However, ref.listen() is updated, but when triggering the other code, the ref.read() gets the previous value.

It appears to only happen for AsyncValue.

To Reproduce

//example_provider.dart
import 'package:flutter/foundation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'example_provider.g.dart';

@riverpod
class Example extends _$Example {
  int counter = 0;

  @override
  Future<String> build() async {
    return "$counter";
  }

  void increment() {
    debugPrint("Updated counter from $counter to ${++counter}");
    state = AsyncData("$counter");
  }
}
//watcher_provider.dart
import 'package:flutter/foundation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

import 'example_provider.dart';

part 'watcher_provider.g.dart';

@riverpod
void eventWatcher(EventWatcherRef ref) {
  ref.listen(exampleProvider, (previous, next) async {
    final readValue = await ref.read(exampleProvider.future);
    debugPrint(
        "Previous: ${previous?.valueOrNull}, next: ${next.valueOrNull}, read: $readValue");
  });
}
//main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mre_riverpod_outdated_read/example_provider.dart';

import 'watcher_provider.dart';

void main() {
  runApp(
    const ProviderScope(
      child: RiverpodEagerInit(
        child: MyApp(),
      ),
    ),
  );
}

class RiverpodEagerInit extends ConsumerWidget {
  const RiverpodEagerInit({super.key, required this.child});

  final Widget child;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    ref.watch(eventWatcherProvider);

    return child;
  }
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends ConsumerWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counter = ref.watch(exampleProvider).maybeWhen(
          data: (data) => data,
          orElse: () => "-1",
        );

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              counter,
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: ref.read(exampleProvider.notifier).increment,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

From debugging:

flutter: Previous: null, next: 0, read: 0
flutter: Updated counter from 0 to 1      // button pressed
flutter: Previous: 0, next: 1, read: 0    // bug occurs, expected read to get "1"

Expected behavior
ref.read() gets the same value as ref.listen() next

@JifScharp JifScharp added bug Something isn't working needs triage labels Dec 20, 2024
@rrousselGit
Copy link
Owner

Could you share something I can run?

@rrousselGit rrousselGit added question Further information is requested and removed needs triage labels Jan 8, 2025
@JifScharp
Copy link
Author

I have updated the code, and pasted in a reproducible example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants