How to set keys for Pages using ValueKey?

2.6k Views Asked by At

I am following this tutorial to add navigation to my app: https://medium.com/flutter/learning-flutters-new-navigation-and-routing-system-7c9068155ade

I don't understand how to create a key for a page. I did some Googling. The error message that I get means that the argument must be a compile-time const, but it makes no sense.

The part in the tutorial that doesn't work for me, but works in the tutorial, because a list of books is compile-time const:

class BookDetailsPage extends Page {
  final Book book;

  BookDetailsPage({
    this.book,
  }) : super(key: ValueKey(book));

I don't want to hardcode a list of books, and I want the app to lookup a book by its book id. A user can provide an arbitrary book id.

class MyBookDetailsPage extends Page {
  final int bookId;

  const MyBookDetailsPage({@required this.bookId})
      : super(key: ValueKey(bookId));

But I get an error

lib/main.dart:311:20: Error: Constant expression expected.
Try inserting 'const'.
      : super(key: ValueKey(bookId));
                   ^^^^^^^^
lib/main.dart:311:20: Error: Constant evaluation error:
      : super(key: ValueKey(bookId));
                   ^
lib/main.dart:311:29: Context: The variable 'bookId' is not a constant, only constant expressions are allowed.
      : super(key: ValueKey(bookId));
                            ^

Adding const doesn't help.

There must be a lot about ValueKey that I don't understand. Please help!

1

There are 1 best solutions below

1
On

If the parameter passed inside ValueKey() is same on rebuilding then the widget will not rebuild because Flutter now knows this widget has a tag.

children: <Widget>[
  if (showFirst) MyTextField(key: ValueKey(1),),
  MyTextField(key: ValueKey(2)),
],

Here we can see ValueKey takes a parameter which we have set to an integer 1, 2. We are free to choose anything as the parameter, but it shouldn’t change on rebuilding.

If you run these changes, the result looks something like this:

This is how output looks