Flutter Hooksを使用して状態管理をスッキリと！

# Flutter Hooks の概要
**Flutter Hooks**とは、Reactの Hooks にインスパイアされた、
Flutterアプリで状態管理を行うためのパッケージです。

このパッケージを使用することで、状態を保持するための 
`StatefulWidget` や `State` クラスの使用が不要になり、
シンプルで直感的なコードを記述することができるようになります。

https://pub.dev/packages/flutter_hooks

# Flutter Hooksの特徴
- **状態フック:** `useState` を使用して、状態を保持することができます。これにより、 `StatefulWidget` の使用を回避し、状態をより直感的に管理できます。

- **useEffectフック:** `useEffect` を使用して、ウィジェットのレンダリング後に関数を
実行します。これにより、画面遷移やAPIリクエストなどの副作用を
簡単に扱うことができます。

- **コンテキストフック:** `useContext` を使用して、コンテキストを取得します。
これによって、ウィジェットツリーの深い階層にある値を簡単に参照できます。

- **その他のフック:** その他にも、 `useMemo` 、 `useCallback` 、 `useReducer` など、
さまざまなフックが提供されています。これらのフックを組み合わせることで、
より柔軟な状態管理が可能になります。

## Flutter Hooksを採用するメリット
- **シンプルなコード:** 状態管理や副作用の処理が簡潔になり直感的なコードを
記述できるため、開発者はコードの可読性を向上させることができます。

- **再利用性の向上:** 画面内で必要な初期処理や、ステートで保持する内容を 
`build` メソッド内に書くことができます。

- **パフォーマンスの向上:** Hooksを使用すると、ウィジェットの再ビルドが
最小限に抑えられます。これにより、不必要な再レンダリングが減少し、
アプリケーション全体のパフォーマンスが向上します。

# 基本メソッド
Flutter Hooks では、 `HookWidget` を継承したウィジェットを作成し、
`use` で始まるフックを使用します。

```dart: HookWidgetを継承
class MyApp extends HookWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
```

:::note info
`riverpod` の機能も同時に使用する場合は、 `hooks_riverpod` をimportした上で、 `HookConsumerWidget` を使用します。
:::


代表的なフックには以下のようなものがあります。

## **useState**
`state` を管理するための関数です。
初期値を引数に渡すと、その値を `state` として保持します。

値を更新する、参照する場合は、 `value` メソッドを使用します。 
`useState` が変数の状態を監視しているため、 `value`　メソッドを使用することで、
画面が再描画され、値を更新することが可能になります。

```dart
import 'package:flutter_hooks/flutter_hooks.dart';

// HookWidgetを継承
class CounterView extends HookWidget {
  @override
  Widget build(BuildContext context) {
    // useStateフックを使用
    final count = useState(0);

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Count: ${count.value}'),
            ElevatedButton(
              onPressed: () => count.value++, // 状態を更新
              child: Text('Increment'),
            ),
          ],
        ),
      ),
    );
  }
}
```

## **useEffect**
初回描画時、または特定の値が更新されたタイミングで呼び出す処理を記載する関数です。 


```dart
final count = useState(0);
useEffect(() {
  //　初回描画時、countが変更されるたびに実行される
  print('Count changed: ${count.value}');
  
  //　　ウィジェットが破棄される時に呼び出される
  return () => print('Cleanup');
}, [count.value]);
```

第一引数には実行したい関数を、第二引数には変更を検知したい変数を配置します。
第二引数は配列で定義することができるため、変数を複数検知することも可能です。

## **useMemoized**
メモ化された値を返す関数です。
値が変更されない限り、前回計算された値が再利用されます。

:::note info
メモ化とは？

同じ結果を返す処理について初回のみ処理を実行して、記録しておき、
値が必要になったら２回目以降は前回の処理結果を計算することなく、
値を得られるようにすることを言います。

メモ化によって都度計算する必要がなくなり、同じ結果を呼び出すため、
パフォーマンスの最適化が期待できます。
:::


- 第一引数: メモ化したい重い計算や作成処理などを行う関数を渡します。
この関数の戻り値がメモ化されます。
- 第二引数: この配列に含まれる値が変更された場合のみ、引数の関数が再実行されます。

以下の例では、2つの数値 `a` 、 `b` の合計値を計算する関数を `useMemoized` で
メモ化しています。 `a` 、 `b` が変更されない限り、合計値の計算は行われません。

```dart
int sum(int a, int b) => a + b;

// ...

final a = useState(1);
final b = useState(2);
final totalSum = useMemoized(() => sum(a.value, b.value), [a.value, b.value]);
```

特に計算コストが高い処理で有効です。
例えば、データの加工、フィルタリング、ソートなどの操作でよく利用されます。

ただし、メモ化されたデータが変更される可能性がある場合は、
useState+ディープコピーなどで対処する必要があります。

# まとめ
Flutter Hooks は、Reactの Hooks に似た状態管理ロジックを導入するパッケージです。
このパッケージを使用することで、 `StatefulWidget` を使わずに状態を
管理することができ、コードの可読性と保守性が向上します。
フックの種類も豊富なので、様々なユースケースに対応することができます。

# 参考資料

https://pub.dev/packages/flutter_hooks#primitives

https://zenn.dev/flutteruniv/books/flutter-architecture/viewer/6_hooks

https://qiita.com/ume-bar/items/13159b93036bd5fe468f

# 告知
最後にお知らせとなりますが、イーディーエーでは一緒に働くエンジニアを
募集しております。詳しくは採用情報ページをご確認ください。

https://eda-inc.jp/recruit/

みなさまからのご応募をお待ちしております。