Pass variable from MaterialPageRoute to custom widget

152

Clean code approach, by isolating your widget rebuild to be as narrow as possible, you are doing things right, but need to move id to your stateful widget.

class FavouritedButton extends StatefulWidget {
final String itemId;
  FavouritedButton({required this.itemId});

  @override
  _FavouritedButtonState createState() => _FavouritedButtonState();
}
class _FavouritedButtonState extends State<FavouritedButton> {
//add initState here, and keep the rest of your widget as it is.
 @override
  void initState() {
  isFavourited();
    super.initState();
  }

Then in your stateless widget:

class SecondScreen extends StatelessWidget {
 final String itemId;

  const SecondScreen({Key? key, required this.itemId}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    
    return Column(children:[
     Text('write some text about your widget or $itemId'),
     FavouritedButton(itemId:itemId)
  ]);
  }
}

This will only rebuild your favorite button.

Share:
152
keymistress
Author by

keymistress

Updated on November 23, 2022

Comments

  • keymistress
    keymistress over 1 year

    A little bit of background: Flutter noob here, trying to build an Add To Favourites function. The list of items sits in a PHP/MySQL database which I access using http on FirstScreen. When user taps on one of the list items, they get redirected to SecondScreen and I pass the 'itemId' using MaterialPageRoute, which has an Add To Favourites button. The 'itemId' of favourited items are stored locally using sqflite. I can access 'itemId' using a StatefulWidget but I haven't been successful trying to create a custom Stateful widget that manages a Stateless Widget, like in this Flutter example on interactivity, i.e. I am unable to access 'itemId' from the custom Stateful widget.

    Code snippet:

    MaterialPageRoute(
      builder: (context) => SecondScreen(
      itemId: item[index].itemId,
    

    My sqflite checkFavourited function:

    Future<bool> checkFavourited(String itemId) async {
            Database db = await instance.database;
            var bookmarked = await db.query(table,
                where: 'itemId = ?',
                whereArgs: [itemId]);
            return bookmarked.isEmpty ? false : true;
          }
    

    Working StatefulWidget:

     bool _isFavourited = false;
    
      void isFavourited() async {
        final isFavourited =
            await DatabaseHelper.instance.checkFavourited(widget.itemId);
        setState(() {
          _isFavourited = isFavourited;
        });
      }
    

    But my attempts to do it in a StatelessWidget have failed. So far I have:

    class SecondScreen extends StatelessWidget {
      final String itemId;
      SecondScreen({
        Key key,
        @required this.itemId,
    

    I get the following error message:

    The getter 'itemId' isn't defined for the type 'FavouritedButton'.
    

    when I try to do this:

    class FavouritedButton extends StatefulWidget {
      @override
      _FavouritedButtonState createState() => _FavouritedButtonState();
    }
    
    class _FavouritedButtonState extends State<FavouritedButton> {
      bool _isFavourited = false;
    
      void isFavourited() async {
        final isFavourited =
        await DatabaseHelper.instance.checkBookmark(widget.itemId);
        setState(() {
          _isFavourited = isFavourited;
        });
      }
      @override
      Widget build(BuildContext context) {
        return IconButton(
          icon: isFavourited
              ? Icon(Icons.bookmark)
              : Icon(
                  Icons.bookmark_border,
                ),
    

    I have read Flutter's Simple app state management and List of state management approaches articles and I might be wrong but is there be an easier solution than Provider or FutureBuilder?

    I know this is a long post and will really appreciate if anyone can give me some pointers on this. Thanks in advance!

  • keymistress
    keymistress over 2 years
    Worked like a charm! Two questions: I added a dispose function after initState and Key key : super(key: key) for the required 'itemId' in the StatefulWidget, are they necessary?
  • Huthaifa Muayyad
    Huthaifa Muayyad over 2 years
    Key's are good only if you use them, they aren't required, but preferred, as your widgets get more complex, keys will enhance performance. As for dispose, it's already built into the widget when it's removed, like initstate, but if you aren't adding any logic in dispose, there is no need to write, and in your widgets, you don't have anything to dispose like streams or listeners or focus nodes.