rodydavis / signals.dart

Reactive programming made simple for Dart and Flutter
http://dartsignals.dev
Apache License 2.0
437 stars 50 forks source link

First signal update doesn't usually get listened to #266

Closed SPiercer closed 4 months ago

SPiercer commented 4 months ago

I have this simple signal i've created to act as a flag/guard to do auth navigation

  @override
  Widget build(BuildContext context) {
    routerGuardSignal.listen(context, () {
      final isUserLoggedIn = routerGuardSignal.value;
      log(isUserLoggedIn.toString());
      while (navKey.currentState!.canPop()) {
        navKey.currentState!.pop();
      }
      if (isUserLoggedIn == true) {
        navKey.currentState!.pushNamed(MainScreen.routeName);
      } else if (isUserLoggedIn == false) {
        navKey.currentState!.pushNamed(LoginScreen.routeName);
      }
    });

this is placed under the material app build context

and from the splash screen i do my check and then i do

routerGuardSignal.value = true or false

sometimes this call make the listener cb invoked and sometimes not

rodydavis commented 4 months ago

It will only be called if the widget is mounted where the listener is created

rodydavis commented 4 months ago

I would suggest an effect outside of the build method to ensure it calling no matter what

SPiercer commented 4 months ago

It will only be called if the widget is mounted where the listener is created

But shouldn't the widget be mounted since this is the root widget ?

rodydavis commented 4 months ago

That should be the case, although I have had weird behavior before with the root widget being mounted.

Can you reproduce a minimal example to test? I'll added it to the widget tests to make sure it's valid.

SPiercer commented 4 months ago

That's minimal enough i can drop everything here in one file

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

final routerGuardSignal = Signal<bool?>(null);

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

  @override
  State<MyApp> createState() => _MyAppState();
}

final navKey = GlobalKey<NavigatorState>();

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    routerGuardSignal.listen(context, () {
      while (navKey.currentState?.canPop() == true) {
        navKey.currentState?.pop();
      }
      final isUserLoggedIn = routerGuardSignal.value;
      if (isUserLoggedIn == true) {
        navKey.currentState!.pushNamed('/main');
      } else if (isUserLoggedIn == false) {
        navKey.currentState!.pushNamed('/login');
      }
    });
    return MaterialApp(
      navigatorKey: navKey,
      routes: {
        '/splash': (_) => const SplashScreen(),
        '/main': (_) => const Scaffold(body:Text('Main')),
        '/login': (_) => const Scaffold(body:Text('Login')),
      },
      initialRoute: '/splash',
    );
  }
}

class SplashScreen extends StatefulWidget {
  const SplashScreen({super.key});

  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    Future.delayed(const Duration(seconds: 2), () async {
     routerGuardSignal.value = true;
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
        body: Text('Splash')
    );
  }
}
rodydavis commented 4 months ago

What is the expected error and what steps do I need to do to reproduce it?

Also is it fixed with an effect or subscribe in initState?

SPiercer commented 4 months ago

Sorry for missing that

Steps to Reproduce

  1. Run the code
  2. wait for the app to open the splash screen
  3. wait two seconds

Expected behavior: App navigates to main page route

Actual behavior: Gets stuck on splash screen


and i tried adding the effect in a separate function away from the context and it worked

rodydavis commented 4 months ago

Definitely sounds like a bug or implementation issue, I think I know what is causing it.

SPiercer commented 4 months ago

Any updates on this ?

rodydavis commented 4 months ago

Just got back from my honeymoon so will be looking at it soon!

SPiercer commented 4 months ago

Oh, Sorry man didn't know

Congratulations on your marriage bro!

On Thu, 23 May 2024 at 23:05, Rody Davis @.***> wrote:

Just got back from my honeymoon so will be looking at it soon!

— Reply to this email directly, view it on GitHub https://github.com/rodydavis/signals.dart/issues/266#issuecomment-2127932844, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJ625GTB3SI7SQCMZMBNHE3ZDZD2NAVCNFSM6AAAAABHYRY3BCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMRXHEZTEOBUGQ . You are receiving this because you authored the thread.Message ID: @.***>

rodydavis commented 4 months ago

Found a fix, and will include on the next update!

iSaqibShafique commented 4 months ago

Just got back from my honeymoon so will be looking at it soon!

🎉 Congratulations, sir, on your marriage! 💍 Wishing you a lifetime filled with love, joy, and endless adventures together. May your journey as a married couple be as enchanting as a fairytale and as vibrant as the brightest stars in the sky. Here's to a future overflowing with happiness, laughter, and unforgettable moments! ❤️

rodydavis commented 2 months ago

Thank you so much 🎉