删除一个元素总是删除颤动中的最后一个

deleting an element always delete the last one in flutter

List storedWishes = [
      {
        'title': 'Phone',
        'description': 'a phone would be nice',
        'price': 200.00,
        'icon': Icon(Icons.phone)
      },
      {
        'title': 'monitor',
        'description': 'need it for a 2 screen setup',
        'price': 350.00,
        'icon': Icon(Icons.tv)
      },
      {
        'title': 'headphones',
        'description': 'need some high quality sound',
        'price': 100.00,
        'icon': Icon(Icons.headset)
      },
    ];
    final wishes = useState(storedWishes);

    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              title: const Text('iWant'),
            ),
            body: Column(
              //map the wishes to a list of wish widgets
              children: wishes.value
                  .map((wish) => Wish(
                        title: wish['title'] as String,
                        description: wish['description'] as String,
                        price: wish['price'] as double,
                        icon: wish['icon'],
                        onDelete: () {
                          wishes.value.remove(wish)
                          wishes.notifyListeners();
                        },
                      ))
                  .toList(),
            )));

wish.dart代码:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

class Wish extends HookWidget {
  const Wish(
      {Key? key,
      this.title = 'default title',
      this.description = 'default description',
      this.price = 0.00,
      this.icon = const Icon(Icons.star),
      this.onDelete})
      : super(key: key);
  final String title;
  final String description;
  final double price;
  final dynamic icon;
  final VoidCallback? onDelete;
  @override
  Widget build(BuildContext context) {
    var wishes = useState({
      'title': title,
      'description': description,
      'price': price,
      'image': icon
    });
    return Card(
        child: Row(children: [
      wishes.value['image'] as Icon,
      Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(wishes.value['title'] as String),
            Text(wishes.value['description'] as String),
          ],
        ),
      ),
      Text((wishes.value['price'].toString()) + '$'),
      Column(
        children: [
          Icon(Icons.edit),
          IconButton(
            onPressed: () {
              onDelete!();
            },
            icon: Icon(Icons.delete),
          )
        ],
      ),
    ]));
  }
}
    //   child: Card(
    //       child: Row(children: [
    //     ,
    //     Column(
    //       crossAxisAlignment: CrossAxisAlignment.start,
    //       children: [
    //         Text('Product name'),
    //         Text('Product description'),
    //       ],
    //     ),
    //     Column(
    //       crossAxisAlignment: CrossAxisAlignment.end,
    //       children: [
    //         Text('Price:'),
    //         Text('21$'),
    //       ],
    //     ),
    //   ])),
    // );

当我点击删除任何其他元素时,点击删除按钮总是删除最后一个元素

edit1:我在点击删除图标后调试打印了数组,数组被正确编辑,但错误的小部件从屏幕上删除

这是一个视频: https://drive.google.com/file/d/1bEjHh4utynZk3QzSWw5gWv__YcpqKkb2/view?usp=sharing

edit2:我已经从愿望小部件中删除了钩子,现在似乎可以正常工作了?无论如何感谢您的帮助:)

这是因为它实际上并没有根据元素的内容来识别元素。当您在列表上调用 remove 函数时,它会看到元素是一个 Map 对象,您的输入也是一个 Map 对象。所以它只是删除了最后一个元素。

您要做的是为每个愿望分配一个唯一标识符。像这样:

      {
        'id': '0'
        'title': 'headphones',
        'description': 'need some high quality sound',
        'price': 100.00,
        'icon': Icon(Icons.headset)
      },

或者如果 title 对于每个项目都是唯一的,那么您也可以参考它。

然后简单地通过编辑你的删除函数做一个深入的比较:

    onDelete: () {
      wishes.value.removeWhere((e) => e["id"] == wish["id"]);
      //OR
      //wishes.value.removeWhere((e) => e["title"] == wish["title"]);
      wishes.notifyListeners();
    },

我不知道为什么它对你不起作用,但它对我来说很好用。因为我不知道你的愿望 class 是什么样子,所以我做了这样的:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
    
void main() {
  runApp(MyApp());
}

class MyApp extends HookWidget {
  @override
  Widget build(BuildContext context) {


List storedWishes = [
      {
        'title': 'Phone',
        'description': 'a phone would be nice',
        'price': 200.00,
        'icon': Icon(Icons.phone)
      },
      {
        'title': 'monitor',
        'description': 'need it for a 2 screen setup',
        'price': 350.00,
        'icon': Icon(Icons.tv)
      },
      {
        'title': 'headphones',
        'description': 'need some high quality sound',
        'price': 100.00,
        'icon': Icon(Icons.headset)
      },
    ];
    final wishes = useState(storedWishes);

    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              title: const Text('iWant'),
            ),
            body: Column(
              //map the wishes to a list of wish widgets
              children: wishes.value
                  .map((wish) => TextButton(
                        child: Text(wish['title'] as String),
                        onPressed: () {
                          wishes.value.remove(wish);
                          wishes.notifyListeners();
                        },
                      ))
                  .toList(),
            )));
  }
}

它像这样正常工作。

编辑:我可以使用您的 Wish 代码重现您的问题。我实际上不熟悉 HookWidget,但将代码更改为此似乎可以修复它。我不知道 useState 的确切用途,但将其排除在外可以解决问题。你甚至可以让 Wish 只扩展 StatelessWidget 而不是 HookWidget

class Wish extends StatelessWidget {
  const Wish(
      {Key? key,
      this.title = 'default title',
      this.description = 'default description',
      this.price = 0.00,
      this.icon = const Icon(Icons.star),
      this.onDelete})
      : super(key: key);
  final String title;
  final String description;
  final double price;
  final dynamic icon;
  final VoidCallback? onDelete;
  @override
  Widget build(BuildContext context) {
    return Card(
        child: Row(children: [
      icon,
      Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(title),
            Text(description),
          ],
        ),
      ),
      Text((price.toString()) + '$'),
      Column(
        children: [
          Icon(Icons.edit),
          IconButton(
            onPressed: onDelete,
            icon: Icon(Icons.delete),
          )
        ],
      ),
    ]));
  }
}