SchabanBo / qlevar_router

Manage you project Routes. Create nested routes. Simply navigation without context to your pages. Change only one sub widget in your page when navigating to new route.
MIT License
86 stars 22 forks source link

Riverpod not loading #115

Closed MichalNemec closed 1 year ago

MichalNemec commented 1 year ago

Hello, im using riverpod and tried now simple route example

QRoute(
      name: Routes.welcome.name,
      path: Routes.welcome.url,
      builder: () => const WelcomePage(),
      pageType: const QPlatformPage(),
    ),

in WelcomePage() im using riverpod to watch for values. Its blank. it seems like riverpod is not triggered at all.

another example is using custom widget in page which has riverpod.. again, completely blank.

What could be the cause?

SchabanBo commented 1 year ago

Hi @MichalNemec , Could provide a sample code for the problem? Because i am using riverpod with qlevar_router in this project and I had no problem with it.

MichalNemec commented 1 year ago
final homeAlertProvider = FutureProvider.autoDispose<GgetAlertData_alert?>((ref) async {
  return await AlertQLService.getActiveAlert();
});

class HomePartialAlert extends ConsumerWidget {
  const HomePartialAlert({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final alert = ref.watch(homeAlertProvider).unwrapPrevious();
    var size = MediaQuery.of(context).size;
    const empty = SliverToBoxAdapter(
      child: SizedBox.shrink(),
    );

    return alert.when(
      data: (data) => data == null
          ? empty
          : SliverPadding(
              padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0),
              sliver: SliverToBoxAdapter(
                child: Align(
                  alignment: Alignment.centerLeft,
                  child: SizedBox(
                    width: size.width >= 600 ? 600 : size.width,
                    child: AnimationLimiter(
                      child: AnimationConfiguration.staggeredList(
                        position: 1,
                        duration: const Duration(milliseconds: 375),
                        child: SlideAnimation(
                          verticalOffset: 50.0,
                          child: FadeInAnimation(
                            child: SWAlert(
                              title: data.title,
                              text: data.text,
                              icon: data.icon,
                              type: SWAlertType.values.byName(data.type),
                              url: data.url,
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
      error: (error, stackTrace) => empty,
      loading: () => empty,
    );
  }
}
class AppRoutes {
  static String homePage = 'Home Page';
  final routes = [
    QRoute(name: homePage, path: '/', builder: () => HomeTab()),   
  ];
}

// Create your app
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp.router(
      routeInformationParser: QRouteInformationParser(),
      routerDelegate: QRouterDelegate(AppRoutes().routes));
}

class HomeTab extends ConsumerStatefulWidget {
  const HomeTab({super.key});

  @override
  ConsumerState<HomeTab> createState() => _HomeTabState();
}

class _HomeTabState extends ConsumerState<HomeTab> with AutomaticKeepAliveClientMixin<HomeTab> {
  bool _shouldKeepAlive = true;

  @override
  bool get wantKeepAlive => _shouldKeepAlive;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return CustomScrollView(
        slivers: [
          const HomePartialAlert(),
          const SliverToBoxAdapter(
            child: SizedBox(
              height: 80,
            ),
          ),
        ],
    );
  }
}

i hope this works. i was trying it on my big project, so i cannot do proper test for now.

SchabanBo commented 1 year ago

So I adjust some things on your example to run it. And it works. Run it and after 5 seconds the widget will be updated as expected.

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:qlevar_router/qlevar_router.dart';

void main(List<String> args) {
  runApp(const ProviderScope(child: MyApp()));
}

final homeAlertProvider = FutureProvider.autoDispose<String?>((ref) {
  return Future.delayed(const Duration(seconds: 5), () => 'Hello');
});

class HomePartialAlert extends ConsumerWidget {
  const HomePartialAlert({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final alert = ref.watch(homeAlertProvider).unwrapPrevious();
    var size = MediaQuery.of(context).size;
    const empty = SliverToBoxAdapter(
      child: SizedBox.shrink(),
    );
    print(alert.value);

    return alert.when(
      data: (data) => data == null
          ? empty
          : SliverPadding(
              padding:
                  const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0),
              sliver: SliverToBoxAdapter(
                child: Align(
                  alignment: Alignment.centerLeft,
                  child: SizedBox(
                    width: size.width >= 600 ? 600 : size.width,
                    child: Text(data),
                  ),
                ),
              ),
            ),
      error: (error, stackTrace) => empty,
      loading: () => empty,
    );
  }
}

class AppRoutes {
  static String homePage = 'Home Page';
  final routes = [
    QRoute(name: homePage, path: '/', builder: () => const HomeTab()),
  ];
}

// Create your app
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) => MaterialApp.router(
      routeInformationParser: const QRouteInformationParser(),
      routerDelegate: QRouterDelegate(AppRoutes().routes));
}

class HomeTab extends ConsumerStatefulWidget {
  const HomeTab({super.key});

  @override
  ConsumerState<HomeTab> createState() => _HomeTabState();
}

class _HomeTabState extends ConsumerState<HomeTab>
    with AutomaticKeepAliveClientMixin<HomeTab> {
  final bool _shouldKeepAlive = true;
  @override
  bool get wantKeepAlive => _shouldKeepAlive;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return const CustomScrollView(
      slivers: [
        HomePartialAlert(),
        SliverToBoxAdapter(
          child: SizedBox(
            height: 80,
          ),
        ),
      ],
    );
  }
}
MichalNemec commented 1 year ago

ill try that, thank you! ill have time tomorrow, so i can try to find the culprit.

MichalNemec commented 1 year ago

@SchabanBo Hello again, i found the issue. Im using catcher and have global navigatorStateKey from that i have In material app init navigatorKey property and in riverpod call for the service im grabbing there context like this

BuildContext? context = navigatorKey.currentState?.context;
if (context == null) return null;

Thats why its null. Why i cant assign navigatorKey OR how to get current context with qlevar_router?

SchabanBo commented 1 year ago

You can do both, To assign the navKey QRouterDelegate(navKey: your Key) To get the current context from any where in the app QR.context

MichalNemec commented 1 year ago

I found QR.context when searching the sourcecode. Maybe you could note it in readme for future :) Thank you for your help!