useFutureとuseStream
FutureBuilder
やStreamBuilder
が楽に書けるようになります。使い方は一緒ですが、Future
の方が使用頻度が多いので、useFuture
を取り上げていきます。
AsyncSnapshot<T> useFuture<T>(
Future<T>? future, {
T? initialData,
bool preserveState = true,
}) {
return use(
_FutureHook(
future,
initialData: initialData,
preserveState: preserveState,
),
);
}
[preserveState]をtrueにすると、Futureのインスタンス(クラスをもとに作成したオブジェクトの実体)が変わった場合でも現在の値を維持することができます。通常はtrueの状態です。useMemoized
を使用して状態を一度保存しないと何度も呼ばれてしまうのでセットで考えて下さい。
useFutureの使用例
final data = useState(0);
final getData = useMemoized(() => getApplicationDocumentsDirectory(), [data.value]);
final dataFuture = useFuture(getData);
useEffect(() {
Future.delayed(const Duration(seconds: 10), () {
data.value += 1;
});
}, [data.value]);
// Flutterの場合、Delayを使用する場合Futureを使う。
final getImageData = useMemoized(
() => getImageSize(
hoge.id, dirSnapshot.hasData ? dirSnapshot.data!.path : null),
[dirSnapshot.data]);
final hogeImageSizeSnapshot = useFuture(getImageData);
useEffect(() {
if (hogeImageSizeSnapshot.hasData &&
hogeImageSizeSnapshot.data != null) {
imageSize.value = hogeImageSizeSnapshot.data;
}
return;
}, [hogeImageSizeSnapshot.hasData]);
useStreamの使用例
class DataCounter extends HookWidget {
const DataCounter({Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
final controller = useStreamController<int>();
return Scaffold(
appBar: AppBar(
title: Text('カウンター'),
),
body: HookBuilder(
builder: (context) {
final count = useStream(controller.stream);
return GestureDetector(
onTap: () => controller.add(count.data! + 1),
child: Text('現在 ${count.data} 回目'),
);
}
),
);
}
}