Я пытаюсь выполнить отмену для элемента списка Dismissible во Flutter, и у меня возникают проблемы с доступом к BuildContext.

У меня есть список флаттера, где каждый элемент - это карточка. Карточка обернута в Dismissible, что позволяет пользователю смахнуть, чтобы закрыть карту. . Dismissible автоматически удаляет элемент из списка. У Dismissible также есть событие onDismissed - я использую это событие для обновления элемента в хранилище состояний Redux (устанавливая для флага isDismissed значение true), а затем показываю SnackBar, который содержит кнопку UNDO.

Здесь у меня проблемы. Я хочу, чтобы кнопка UNDO восстановила элемент, отправив другое действие в хранилище Redux, чтобы установить isDismissed в false. Для этого мне нужен контекст, из которого можно получить диспетчера магазина. Однако, когда я пытаюсь использовать приведенный ниже код, я получаю сообщение об ошибке при нажатии UNDO:

Поиск предка деактивированного виджета небезопасен

class ProductCard extends StatelessWidget {
  final Product product;

  const ProductCard(this.product);

  @override
  Widget build(BuildContext context) {
    return Dismissible(
      key: Key(product.id.toString()),

      onDismissed: (direction) {
        StoreProvider.of<AppState>(context).dispatch(DismissAction(product));

        // Then show a snackbar to allow undo
        Scaffold.of(context).showSnackBar(
            SnackBar(
                content: Row(
                  children: <Widget>[
                    Expanded(child: Text("Dismissed ${product.title}"),),
                    FlatButton(
                      onPressed: () {
                        // THIS IS WHERE I GET THE ERROR
                        StoreProvider.of<AppState>(context).dispatch(UndoDismissAction(product));
                      },
                      child: Text("UNDO"),
                    )
                  ],
                )
            )
        );
      },

      child: Card(
        child: ...
      )
    );
  }
}

Из того, что я прочитал, я думаю, что происходит то, что строка StoreProvider.of<AppState>(context) внутри действия onPressed кнопки отмены пытается использовать контекст, который принадлежит карте, но поскольку карта была удалена из списка , его больше не существует.

Я не знаю, как это обойти. Я читал о флаттер-ключах и думаю, что ответ может заключаться в том, чтобы начать передавать какой-то глобальный ключ, но я не могу понять, как это работает. Я попробовал и столкнулся с другой проблемой с 'inheritFromWidgetOfExactType' was called on null. Ключи - решение этой проблемы? Если да, то где мне создать ключ, передать ли его виджету, какой тип ключа следует использовать и т. Д., Или есть лучшее решение?

Большое спасибо!

0
James Allen 14 Окт 2019 в 20:48

1 ответ

Лучший ответ

Извлеките одну копию хранилища в локальную переменную, которая затем будет захвачена всеми лямбда-выражениями, указанными ниже.

  @override
  Widget build(BuildContext context) {
    var store = StoreProvider.of<AppState>(context);
    return Dismissible(
    ...
         store.dispatch(DismissAction(product));
0
Richard Heap 14 Окт 2019 в 18:16