How to load app state asynchronously from server while creating store in flutter redux?

Issue

Basically I want to load firebase remote config parameters when app starts and store it in app state while creating store.

So that whenever I need it I just fetch it from store and get remoteConfig value.

class App extends StatelessWidget {
// Get firebase remote config and store it in appState 
 ---> final store = createStore();

 App();

  @override
  Widget build(BuildContext context) {
    return new PersistorGate(
      persistor: persistor,
      loading: new LoadingScreen(),
      builder: (context) => new StoreProvider<AppState>(
          store: store,
          child: new MaterialApp(
            title: 'TestApp',
            theme: defaultTargetPlatform == TargetPlatform.iOS
                ? kIOSTheme
                : kDefaultTheme,
            routes: getRoutes(context, store),
            initialRoute: '/login',
          )),
    );
  }
}

Create Store file –

Store<AppState> createStore() { 
    Store<AppState> store = new Store(
        appReducer,
        // store remote config in initial app state
        initialState: new AppState(),
        middleware: createMiddleware(),
    );
    persistor.load(store);

    return store;
}

Solution

I followed this approach –

  1. Use FutureBuilder
  2. Fetched remote config asynchronously in future
  3. Created store with fetched remoteConfig

I implemented following solution –
Looking for any other possible approach than this.

Edit:

There can be cases when you will not be getting the remote config from firebase or some async operation failed in that case you will have to check if snapshot has data and display some fallback ui.

e.g

if(snapshot.hasData) {
  // render component
} else {
  // render loader
}

Code:

 @override
  Widget build(BuildContext context) {
    return new FutureBuilder<Store>(
        future: setupRemoteConfig(),
        builder: (BuildContext context, AsyncSnapshot<Store> snapshot) {
          return new PersistorGate(
            persistor: persistor,
            loading: new LoadingScreen(),
            builder: (context) =>
            new StoreProvider<AppState>(
                store: snapshot.data,
                child: new MaterialApp(
                  title: 'Test App',
                  theme: defaultTargetPlatform == TargetPlatform.iOS
                      ? kIOSTheme
                      : kDefaultTheme,
                  routes: getRoutes(context, snapshot.data),
                  initialRoute: '/login',
                )
            ),
          );
        }
    );
  }

RemoteConfig:
Fetching remoteConfig async way

  Future<Store> setupRemoteConfig() async {
    final RemoteConfig remoteConfig = await RemoteConfig.instance;
    // Enable developer mode to relax fetch throttling
    remoteConfig.setConfigSettings(new RemoteConfigSettings(debugMode: true));
    remoteConfig.setDefaults(<String, dynamic>{
      'welcome': 'default welcome',
    });

    await remoteConfig.fetch(expiration: const Duration(hours: 5));
    await remoteConfig.activateFetched();

    return createStore(remoteConfig);

  }

Creating Store:

Store<AppState> createStore(RemoteConfig config) {
    Store<AppState> store = new Store(
        appReducer,
        initialState: new AppState(config: config),
        middleware: createMiddleware(),
    );

    persistor.load(store);

    return store;
}
  • Persistor is coming from

    import ‘package:redux_persist_flutter/redux_persist_flutter.dart’;

it used to rehydrate old state in store.

Answered By – WitVault

Answer Checked By – Willingham (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *