🥮

flutter_hooksでuseContextを使用した活用例

2023/12/16に公開

Overview

公式のリファレンスを見てみたが役立つ情報が無かった😅
https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useContext.html

BuildContext useContext() 構築する HookWidget の BuildContext を取得します。

コードジャンプして内部を見に行くとこんなコードが書かれていた。

/// Obtains the [BuildContext] of the building [HookWidget].
BuildContext useContext() {
  assert(
    HookElement._currentHookElement != null,
    '`useContext` can only be called from the build method of HookWidget',
  );
  return HookElement._currentHookElement!;
}

📕翻訳すると

/// ビルド[HookWidget]の[BuildContext]を取得します。
BuildContext useContext() {
   主張する(
     HookElement._currentHookElement != null、
     `useContext` は HookWidget の build メソッドからのみ呼び出すことができます'、
   );
   HookElement._currentHookElement を返します!;
}

summary

useContextは、Flutter Hooksの一部であり、現在のBuildContextを取得するために使用されます。BuildContextは、ウィジェットツリーの位置に関する情報を持ち、テーマやナビゲーションなどのウィジェットの親に関連する情報にアクセスするために使用されます。

以下に、useContextを使用してテーマの色にアクセスする例を示します。

Theme Colorを変更する
class MyWidget extends HookWidget {
  
  Widget build(BuildContext context) {
    final context = useContext();
    final theme = Theme.of(context);

    return Container(
      color: theme.primaryColor,
    );
  }
}

React.jsのカスタムフックのようなものを作って、ビルドメソッドの中に、書かないように対策することができます。

SnackBarControllerというスナックバーを出すクラスを定義して、useSnackBarを定義する。データの型にSnackBarControllerを使う。returnで戻り値として、返すSnackBarControllerに、useContextを使って、ウィジェットツリーの情報にアクセスできるようにする。

カスタムHookでuseContextを使う
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

// HookWidgetで使用するカスタムHook
SnackBarController useSnackBar() {
  final context = useContext();
  return SnackBarController(context: context);
}

// スナックバーを出すクラス
class SnackBarController {
  final BuildContext context;

  SnackBarController({required this.context});

  void show(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(backgroundColor: Colors.green, content: Text(message)),
    );
  }
}

class CustomHook extends HookWidget {
  const CustomHook({super.key});

  
  Widget build(BuildContext context) {
    final context = useContext();
    final theme = Theme.of(context);
    final snackBarController = useSnackBar();

    return Scaffold(
      appBar: AppBar(
        backgroundColor: theme.primaryColorDark,
        title: const Text('Custom Hook'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () => snackBarController.show('Hello, World!'),
          child: const Text('Show SnackBar'),
        ),
      ),
    );
  }
}

ボタンを押すと、こんな感じでスナックバーを出すことができます。

thoughts

useContext は HookWidget の build メソッドからのみ呼び出すことができます。確かにその通りで以前、Widgetを切り分けると、Dialog使ったときに、エラーが出ました笑
でも今回のような方法を使えば、スナックバーを使えているので、Widgetのエラーを出すこともないし、BuildContextを使って、Widgetの値を渡すことができるようになります。

Discussion