Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent passing down BuildContext?

Tags:

flutter

dart

Currently I get the BuildContext from the build method in HomeScreen, and then I have to pass it down to _gridSliver then down to _storeCard.

How can I write the code so that I don't need to pass the context down?

Maybe I can create a new private StatelessWidget called _StoreCard that will have its own build method and thus its own BuildContext?

class HomeScreen extends StatelessWidget {
  HomeScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, List<MyStore.Store>>(
        converter: (Store<AppState> store) => store.state.home.stores,
        builder: (BuildContext context, List<MyStore.Store> stores) =>
            CustomScrollView(slivers: <Widget>[_gridSliver(stores, context)]));
  }

  Widget _gridSliver(stores, context) {
    return SliverGrid(            
        delegate: SliverChildListDelegate(List<Widget>.from(stores.map(_storeCard, context))));
  }

  Widget _storeCard(MyStore.Store store, BuildContext context) {
    return InkWell(
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (_) => StoreScreen(storeId: store.id)),
        );
      },
      child: Container(child: Text(store.name))
    );
  }
}

Another instance of this problem is I navigate on a child function.

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      WhiteButton(text: "Login with Facebook", onPressed: _loginWithFacebook),
      WhiteButton(text: "Login with Google", onPressed: _loginWithGoogle),
    ])
  )
}

_loginWithFacebook(context) async {
    ...
    var user = User.fromFacebook(result.accessToken.token, json.decode(graphResponse.body));
    await _login(user, context);
  }
}

_loginWithGoogle(context) async {
    ...
  GoogleSignInAccount googleUser = await _googleSignIn.signIn();
  await _login(User.fromGoogle(googleUser), context);
}

_login(user, context) async {
  var fetchedUser = await MeService.getUser(user);
  if (fetchedUser != null) {
    loginSuccess(fetchedUser);
    Navigator.popUntil(context, ModalRoute.withName(MainRoutes.root));
  } else {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (_) => RegisterScreen(user: user)),
    );
  }
}
like image 255
psyanite Avatar asked Mar 05 '23 00:03

psyanite


1 Answers

To get a new BuildContext, you have two main solutions:

  • Extract part of the subtree into a new widget, typically StatelessWidget. And then use it's BuildContext from the build method

  • Use Builder widget, which is basically a reusable widget made to obtain a BuildContext:

Example:

 @override
 Widget build(BuildContext context) {
  return Builder(
    builder: (context) {
      // do something with this new context
    },
  );
}
like image 98
Rémi Rousselet Avatar answered Mar 20 '23 21:03

Rémi Rousselet