[コラム]StatefulWidgetクラスのStateオブジェクト内で定義されたインスタンス変数を他のWidgetやMethodに渡す方法

1.直接子Widgetに引数として渡す

最も簡単な方法の一つは、子ウィジェット(データを渡したい側)のコンストラクタを通じて直接データを渡す方法です。
これは、特に小規模なアプリケーションや単純なウィジェットツリーの場合に有効です。

Dart
//⓸データを受取りたい側のクラス
class CustomWidget extends StatelessWidget {
  final List<Map<String, dynamic>> cates; //⓹受取りたいデータの器

  //⓺ここでコンストラクタの引数として直接データを渡す
  const CustomWidget({Key? key, required this.cates}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: cates.length,  //←⓻ここで利用できる
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(cates[index]['description']),  //←⓻ここで利用できる
        );
      },
    );
  }
}
//⓵データを渡したい側のクラス
class TabBarPageState extends State<TabBarPage> {
  List<Map<String, dynamic>> cates = [];  //⓶渡したいデータ

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Categories")),
      body: CustomWidget(cates: cates), //←⓷ここで渡す
    );
  }
}

2.InheritedWidgetを使用する

上記以外に、InheritedWidget を使用する方法があります。
InheritedWidget は、ウィジェットツリーを通じてデータを効率的に渡すために設計されています。

Dart
//データ中継用クラス(再利用可能(同じデータ型の場合))
//・クラス名は任意
//・InheritedWidget継承(extends InheritedWidget)必須
class CatesProvider extends InheritedWidget {
  //中継対象となるデータ型定義
  final List<Map<String, dynamic>> cates;  // ← ここで宣言する
  //中継用コンストラクタ
  const CatesProvider({
    Key? key,  //キー(必須)
    required this.cates,  // ← ここで中継データを設定する
    required Widget child,  //子ウィジェット(必須)
  }) : super(key: key, child: child);
  //探索用メソッド(必須)
  static CatesProvider? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<CatesProvider>();
  }
  //提供データ更新メソッド(必須)
  //・メソッド名は固定
  @override
  bool updateShouldNotify(CatesProvider oldWidget) {
    return oldWidget.cates != cates;  // ← ここで比較する
  }
}

//データを渡したい側(親ウィジェット側)のクラス
class TabBarPageState extends State<TabBarPage> {
  List<Map<String, dynamic>> cates = [];  // ← 源泉となるデータ

  @override
  Widget build(BuildContext context) {
    //データ中継用クラス(ThisEx: 'CatesProvider')
    //のラップ範囲(スコープ(ThisEx: 'Scaffold'含む))に
    //データ(ThisEx: 'cates')を伝播する
    //(故に子ウィジェットに(データ(ThisEx: 'cates')が伝播される)
    return CatesProvider(
      cates: cates,  // ← 伝播するデータ
      child: Scaffold(
        appBar: AppBar(title: Text("Categories")),
        body: CustomWidget(),  // ← データを貰いたい側(子ウィジェット)のクラス
                               //   (重要)引数無し!!
      ),
    );
  }
}

//データを貰いたい側(子ウィジェット)のクラス
//(いわゆる'カスタムウィジェット'と言われているもの)
class CustomWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //データ中継用クラス(ThisEx: 'CatesProvider')からデータ受取
    final cates = CatesProvider.of(context)?.cates ?? [];  //←データを受取る

    return ListView.builder(
      itemCount: cates.length,  //←ここでデータを利用する
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(cates[index]['description']),  //←ここでデータを利用する
        );
      },
    );
  }
}

3.状態管理ライブラリを使用する

大規模なアプリケーションや、より複雑な状態管理が必要な場合、
・Provider
・Riverpd
・Bloc
等の状態管理ライブラリを使用すると便利です。
これらのライブラリはデータの共有と更新を簡単に行え、コードの保守性を向上させます。

こちらについては、別記事を参照願います。

コメントを残す