简体   繁体   English

Flutter Riverpod Statenotifier 应在 map 更改时重建

[英]Flutter Riverpod Statenotifier should rebuild on map changes

My statenotifier does not rebuild when the map changes.当 map 更改时,我的 statenotifier 不会重建。 I think the issue is that the map is inside another class.我认为问题在于 map 在另一个 class 内。 I use riverpod and i've seen it work with lists so I tested with a List inside a class and filter rebuilds to that class.我使用riverpod,并且我已经看到它可以与列表一起使用,因此我在class 中使用列表进行了测试,并将过滤器重建为该class。 But no success但没有成功

StateNotifier using copyWith to replace a map does not trigger rebuild
class Admin {
  const Admin({
    this.admin = const {},
  });

  final Map<int, List<String>> admin;

  Admin copyWith({
    Map<int, List<String>>? admin,
  }) {
    return Admin(
      admin: admin ?? this.admin,
    );
  }
}

class Member {
  const Member({
    this.wordOfTheDay = "",
    this.admin = const Admin(),
  });

  final Admin admin;
  final String wordOfTheDay;

  Member copyWith({
    Admin? admin,
    String? wordOfTheDay,
  }) {
    return Member(
      admin: admin ?? this.admin,
      wordOfTheDay: wordOfTheDay ?? this.wordOfTheDay,
    );
  }
}

class MemberNotifier extends StateNotifier<AsyncValue<Member>> {
  MemberNotifier() : super(const AsyncValue.loading());

  final Map<int, List<String>> admins = {};

  void loadMembers(String id, String item) {
    admins[id]!.add(item);
    state = state.whenData((value) => value.copyWith(admin: state.value!.admin.copyWith(admin: admins)));
  }
}

final watch = ref.watch(memberNotifierProvider.select((member) => member.value!.admin));

I'm working through a similar issue today with Maps not being copied correctly using Freezed and Riverpod.我今天正在解决一个类似的问题,即使用 Freezed 和 Riverpod 无法正确复制地图。 I'm reading through this github issue, maybe it'll help you too.我正在阅读这个 github 问题,也许它也会对您有所帮助。 https://github.com/rrousselGit/freezed/issues/185 https://github.com/rrousselGit/freezed/issues/185

We can pass the Map values and set the values in Map<String,dynamic> like this:-我们可以传递 Map 值并在 Map<String,dynamic> 中设置值,如下所示:-

Provider提供者

 final counterProvider =
        StateNotifierProvider<Counter, Map<String, dynamic>>((_) => Counter());

class Counter extends StateNotifier<Map<String, dynamic>> {
  // Counter(Map<String, dynamic> data): super(data);
  Counter() : super({});

  void displayFile(String name, String email, String address) {
    Map<String, dynamic> cartMap = {"name": name, "email": email, "address": address};

    state = {...state, ...cartMap};
  }
}

After that we can fetch the values of Map using this way in Riverpod with HooksConsumerWidget:-之后,我们可以在 Riverpod 中使用 HooksConsumerWidget 获取 Map 的值:-

class MyHomePage extends HookConsumerWidget {
  MyHomePage({Key? key}) : super(key: key);

  TextEditingController nameController = TextEditingController();
  TextEditingController emailController = TextEditingController();
  TextEditingController addressController = TextEditingController();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final dataValue = ref.watch(counterProvider);
    String name = dataValue['name'].toString();
    String email = dataValue['email'].toString();
    String address = dataValue['address'].toString();
    print(dataValue);
    return Scaffold(
        appBar: AppBar(
          title: const Text(' demo'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(15.0),
          child: Column(
            children: [
              TextFormField(
                controller: nameController,
                keyboardType: TextInputType.text,
                decoration: const InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: 'Enter name',
                ),
              ),
              const SizedBox(
                height: 10,
              ),
              TextFormField(
                controller: emailController,
                keyboardType: TextInputType.text,
                decoration: const InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: 'Enter email',
                ),
              ),
              const SizedBox(
                height: 10,
              ),
              TextFormField(
                controller: addressController,
                keyboardType: TextInputType.text,
                decoration: const InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: 'Enter address',
                ),
              ),
              const SizedBox(
                height: 10,
              ),
              ElevatedButton(
                  onPressed: () {
                    ref.read(counterProvider.notifier).displayFile(
                        nameController.text,
                        emailController.text,
                        addressController.text);
                  },
                  child: const Text('Show Details')),
              const SizedBox(
                height: 20,
              ),
              Text(name),
              const SizedBox(
                height: 10,
              ),
              Text(email),
              const SizedBox(
                height: 10,
              ),
              Text(address),
            ],
          ),
        ));
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM