【Riverpod】Listの値を更新したのにref.watchで再描画されない

8976 ワード

事象

watch している状態が更新されているはずなのに、再描画されないことがありました。

事象が起こったコードを単純化すると以下のような感じです。

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

class Hoge extends ConsumerWidget {
  Hoge({Key? key}) : super(key: key);

  final StateProvider<List<String>> _hogeListProvider =
      StateProvider((ref) => ['hoge', 'fuga']);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final hogeList = ref.watch(_hogeListProvider);
    return Column(
      children: [
        Column(
          children: List.generate(
            hogeList.length,
            (index) {
              return Text(hogeList[index]);
            },
          ),
        ),
        ElevatedButton(
          child: Container(
            color: Colors.blue,
          ),
          onPressed: () {
            // リストに'fuga'がなければ追加、あれば削除
            if (hogeList.contains('fuga')) {
              hogeList.remove('fuga');
            } else {
              hogeList.add('fuga');
            }
            // 削除or追加したリストをstateに代入する
            ref.read(_hogeListProvider.notifier).state = hogeList;
          },
        )
      ],
    );
  }
}

何らかのメソッドで、状態管理の対象となっているhogeListの操作を行い、状態を更新。
一見正しく状態の更新が行われているように見えたのですが、再描画されませんでした。

解決策

状態の更新を以下のように書き換えると再描画されました

- ref.read(_hogeListProvider.notifier).state = hogeList;
+ ref.read(_hogeListProvider.notifier).state = [...hogeList];

原因

原因ははっきりとは分かりませんが、List の中身を変えただけでは List 自体の参照(メモリ番地)が変わらないため、変化があったとみなされないのでしょうか?
詳しい方いらっしゃったらコメント頂けると助かります 🙇🏻‍♂️