はじめに
Flutter Hooks は Flutter で React Hooks のように useState
useEffect
useCallback
などのフックを使用できるライブラリです。
この記事では上記で挙げた3つのフックに焦点を当て、 Flutter Hooks と React Hooks の違いをまとめます。
useState
ローカルなステートを扱うためのフックです。
簡単なカウンターコンポーネント(カウンターウィジェット)を作成して違いを見ていきます。
React Hooks
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>count: {count}</p>
<button
type="button"
onClick={() => setCount((prev) => prev + 1)}
>
add
</button>
</div>
);
};
Flutter Hooks
state.value
で値にアクセスできます。また、値を更新するための関数は定義せず、 state.value
の値を直接書き換えます。
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
class Counter extends HookWidget {
const Counter({super.key});
@override
Widget build(BuildContext context) {
final count = useState(0);
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('count: ${count.value}'),
TextButton(
onPressed: () {
count.value += 1;
},
child: const Text('add'),
),
],
),
);
}
}
useEffect
副作用を実行することを可能にするフックです。
先程のカウンターコンポーネントを使用し、コンソールに値を表示するようにします。
React Hooks
参考: フック API リファレンス - useEffect
import React, { useState, useEffect } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`count: ${count}`);
}, [count]);
return (
...
);
};
Flutter Hooks
React Hooks と書きっぷりはほとんど同じですが、違う点もあります。
didMount & didUpdate are called after the render
initState & didUpdateWidget are called before the renderSimilarly, when unmounting a Component tree, React will call willUnmount on parents first and go down the tree.
But Flutter does the opposite. It calls dispose on leaves first and goes up the tree.
引用: https://github.com/rrousselGit/flutter_hooks/issues/63#issuecomment-474994331
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
class Counter extends HookWidget {
const Counter({super.key});
@override
Widget build(BuildContext context) {
final count = useState(0);
useEffect(() {
debugPrint('count: ${count.value}');
return null;
}, [count.value]);
return ...
}
}
useCallback
メモ化されたコールバックを返すフックです。
先程 useEffect
内で記述した処理を関数として定義します。
React Hooks
参考: フック API リファレンス - useCallback
import React, { useState, useEffect, useCallback } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const outputLog = useCallback(() => {
console.log(`count: ${count}`);
}, [count]);
useEffect(() => {
outputLog();
}, [outputLog]);
return (
...
);
};
Flutter Hooks
useCallback
に関しても書きっぷりはほとんど変わりません。
参考: useCallback function
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
class Counter extends HookWidget {
const Counter({super.key});
@override
Widget build(BuildContext context) {
final count = useState(0);
final outputLog = useCallback(() {
debugPrint('count: ${count.value}');
}, [count.value]);
useEffect(() {
outputLog();
return null;
}, [outputLog]);
return ...
}
}
おわりに
今回 Flutter Hooks と React Hooks を比べてみましたが、ほとんど書き方に差はなく、どちらかの知識があればもう片方も書くことができるのが見て取れたと思います。今まではネイティブアプリを作成する際は React に慣れていることもあり、 React Native を用いることが多かったのですが、 Flutter Hooks を知ってからは Flutter でも同様に開発を行うことができるため選択肢の幅が広がったと思います。