marcglasberg / async_redux

Flutter Package: A Redux version tailored for Flutter, which is easy to learn, to use, to test, and has no boilerplate. Allows for both sync and async reducers.
Other
230 stars 41 forks source link

Feature Request: onInit method similar to flutter_redux #98

Closed archie-sh closed 3 years ago

archie-sh commented 3 years ago

Hi, I need to load data from the backend and run business logic when the app starts. flutter_redux has a onInit method that gets the store passed as an argument, maybe a similar implementation can be added to async_redux.

My current workaround is to use FutureBuilder:

Store<AppState> store;

class SampleApp extends StatefulWidget {
  @override
  _TidelyAppState createState() => _TidelyAppState();
}

class _SampleAppState extends State<SampleApp> {
  Future<bool> _data;

  @override
  void initState() {
    super.initState();
    _data = initApp();
  }

  Future<bool> initApp() async {
    await store.dispatchFuture(InitApp());
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      initialData: false,
      future: _data,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return StoreProvider<AppState>(
            store: store,
            child: MaterialApp(
              title: 'Sample',
              localizationsDelegates: context.localizationDelegates,
              supportedLocales: context.supportedLocales,
              locale: context.locale,
              theme: ThemeData(
                pageTransitionsTheme: NoTransitionsOnWeb(),
                brightness: Brightness.light,
                primarySwatch: Colors.blue,
                visualDensity: VisualDensity.adaptivePlatformDensity,
              ),
              navigatorKey: navigatorKey,
              navigatorObservers: [
                SentryNavigatorObserver(),
              ],
              onGenerateRoute: SampleRouter.generateRoute,
            ),
          );
        } else {
          return const Center(child: CircularProgressIndicator());
        }
      },
    );
  }
}
marcglasberg commented 3 years ago

What you are doing is fine, but there are other options. You are assuming the store can't exist before some info in it is initialized, but that's not true. Some store.state.isInitialized flag can indicate if the store is initialized or not.

Start by removing the FutureBuilder, and your onGenerateRoute should call your home-page widget, HomePageConnector, which is a connector that checks the store.state.isInitialized flag:

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, _Vm>(
      vm: () => _Factory(),
      builder: (context, vm) {
        if (vm.isInitialized) {
           if (vm.isLoggedIn) return HomePage();
           else return LoginPage();
        }     
       else
          return const Center(child: CircularProgressIndicator());
      },
    );
  }