Closed wiseaidev closed 10 months ago
@wiseaidev I tested with the version below.
flutter 3.3.10: works
fvm use 3.3.10
fvm flutter run
💪 Running with sound null safety 💪
An Observatory debugger and profiler on sdk gphone64 x86 64 is available at: http://127.0.0.1:57926/_bj4TiIsICo=/
The Flutter DevTools debugger and profiler on sdk gphone64 x86 64 is available at: http://127.0.0.1:9100?uri=http://127.0.0.1:57926/_bj4TiIsICo=/
E/SurfaceSyncer(13927): Failed to find sync for id=0
W/Parcel (13927): Expecting binder but got null!
I/flutter (13927): Am action has been fired!
I/flutter (13927): A reaction has been triggered! AppPage.home
D/EGL_emulation(13927): app_time_stats: avg=1251.68ms min=84.12ms max=2419.23ms count=2
I think you are mistaken because the reaction only happens once.
The reaction occurs only when the observable's value is a different value from the previous one.
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
import 'package:mobx_autorun_issue/store.dart';
import 'package:provider/provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
Provider(
create: (_) => AppState()..initialize(),
child: const MyApp(),
),
);
}
var reactionTriggered = false;
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
// final appState = context.read<AppState>();
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: ReactionBuilder(
builder: (context) {
return reaction(
(_) => context.read<AppState>().currentPage,
(v) {
print("A reaction has been triggered! $v");
reactionTriggered = true;
},
);
},
child: Observer(
name: "CurrentScreen",
builder: (context) {
switch (context.read<AppState>().currentPage) {
case AppPage.splash:
return const MySplashPage(title: "Splash Page");
case AppPage.home:
return const MySplashPage(title: "Home Page");
case AppPage.login:
return const Placeholder();
}
},
),
),
);
}
}
class MySplashPage extends StatefulWidget {
const MySplashPage({super.key, required this.title});
final String title;
@override
State<MySplashPage> createState() => _MySpashPageState();
}
class _MySpashPageState extends State<MySplashPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
print("Am action has been fired!");
context.read<AppState>().goTo(
AppPage.home,
);
},
tooltip: 'Smash It.',
child: const Icon(Icons.app_registration_outlined),
),
);
}
}
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mobx_autorun_issue/main.dart';
import 'package:mobx_autorun_issue/store.dart';
import 'package:provider/provider.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(TestApp());
expect(reactionTriggered, false);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.app_registration_outlined));
await tester.pump();
// Verify that our counter has incremented.
expect(reactionTriggered, true);
});
}
class TestApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Provider(
create: (_) => AppState()..initialize(),
child: const MyApp(),
);
}
}
fvm use 3.7.0
fvm flutter test
00:02 +0: Counter increments smoke test
Am action has been fired!
A reaction has been triggered! AppPage.home
00:02 +1: All tests passed!
@amondnet I'm sorry, I really don't understand what's wrong here 😂, but here are two code examples + video, in one case the reaction works, in the other it doesn't.
mobx store class -
import 'package:mobx/mobx.dart';
part 'reaction_builder_mobx.g.dart';
class Counter = CounterBase with _$Counter;
abstract class CounterBase with Store {
@observable
var value = 0;
@action
void increment() {
value++;
}
@action
void decrement() {
value--;
}
}
first code example (doesn`t work)
return ReactionBuilder(
builder: (context) => reaction(
(_) => Provider.of<Counter>(context).value,
(res) {
log.d('current counter value - $res');
if (res != 10) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('current counter val - $res == 10!!!'),
));
},
),
child: .....
and the second one (everything is the same except for access to the provider)
final counter = Provider.of<Counter>(context);
return ReactionBuilder(
builder: (context) => reaction(
(_) => counter.value,
(res) {
log.d('current counter value - $res');
if (res != 10) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('current counter val - $res == 10!!!'),
));
},
),
child: ...
@RossHS
Provider.of<Counter>(context).value
=>Provider.of<Counter>(context, listen: false).value
or context.read<Counter>().value
https://github.com/rrousselGit/provider#reading-a-value
return ReactionBuilder(
builder: (context) => reaction(
(_) => Provider.of<Counter>(context, listen: false).value,
(res) {
log.d('current counter value - $res');
if (res != 10) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('current counter val - $res == 10!!!'),
));
},
),
child: .....
@amondnet You are right, thank you very much. All because of my inattention 🌚
Hey folks,
Thanks for your contributions to the conversation. I tried both of your suggestions in the app I am currently building, but, unfortunately, it is still not working.
The reaction occurs only when the observable's value is a different value from the previous one.
Exactly. But the thing is that it is not triggered for the first time. I think the first image I shared is somewhat misleading. However, I am not sure what is wrong, Mobx? Provider? Flutter? Gradle? Android studio? I literally have no idea. However, for now, I am going to downgrade flutter to the version that was working before.
I think that's enough flutter for the week cause this issue is so trippy. I will keep you updated on this matter. Have fun!
Hey everyone. I just wanted to give you an update on the previous issue. I found that the issue is reproducible on the current version of flutter, as shown in the following image:
However, if you try to change the lower bound of the SDK versions to
2.16.8
, the function works as expected:It seems like the widget's behavior has changed in the newer flutter version. In particular, it appears that the constructor has been updated in a way that causes this issue.
Have a look at the previous ticket for more details on this issue.