just_hook 0.0.2
just_hook: ^0.0.2 copied to clipboard
A lightweight, robust, and structurally complete Flutter Hooks framework inspired by React Hooks. Features state, effect, animation, HTTP, and form management.
just_hook #
A lightweight and simple open-source Flutter hooks framework inspired by flutter_hooks and React Hooks.
HookBuilder #
Need hooks in a regular StatelessWidget or StatefulWidget? Use HookBuilder:
Widget build(BuildContext context) {
return Scaffold(
body: HookBuilder(
builder: (context) {
final state = useState(0);
return Center(child: Text('${state.value}'));
},
),
);
}
Features Deep Dive #
Provides building blocks to compose reusable behavior and state logic.
Standard Hooks #
useState: Manages mutable state and rebuilds the widget automatically.useEffect: Manages side effects related to your widget's lifecycle.useMemoized: Caches a complex computation, recalculating only if dependencies change.
Advanced Hooks #
useFuture: Subscribes to aFutureand returns theAsyncSnapshotstate.useStream: Subscribes to aStreamand returns theAsyncSnapshotstate.useTextEditingController: Creates an automatically disposableTextEditingController.useSearch: Easily builds a text editing controller and text state listener for building search UIs.
Controller & Utility Hooks #
usePrevious: Returns the previous value given to it, useful for comparing previous vs new state.useScrollController: Creates an automatically disposableScrollController.usePageController: Creates an automatically disposablePageController.useFocusNode: Creates an automatically disposableFocusNode.useIsMounted: Returns a function evaluated to true if the widget is currently mounted.useValueListenable: Subscribes to aValueListenableautomatically triggering rebuilds.useListenable: Subscribes to aListenablemaintaining proper disposal/listener attachments.useDebounced: Returns a debounced version of a value to avoid rapid continuous rebuilds or side-effects.
Domain-Specific Hooks #
usePagination: Easily handle typical infinite-scrolling scenarios. Manages data fetching, appending, refresh, and loading states automatically.useForm: A robust, uncontrolled form controller pattern for reactive form state handling and validation without heavy internal boilerplate. Easily registers form fields, controls submission loading, and automatically renders validation errors.useAnimationController: Creates anAnimationControllerseamlessly. Automatically provides aTickerProviderto the hook behind the scenes, mimicking the natural Fluttervsyncrequirement without needing Stateful widget mixins.useQuery: An advanced, React-Query influenced hook designed exclusively for fetching HTTP REST API logic. Completely tracks cache states likeisLoading,isFetching,data,errorand explicitrefetch()commands globally.useMutation: The counterpart touseQuery, designed to handle POST/PUT updates natively exposing anisMutatingstate. ProvidesonSuccess,onError,- π Query & Mutations:useQuery,useMutation,useSubscriptionβ built-in support for REST or GraphQL-like data fetching.- πΌοΈ UI & Layout:
useTheme,useMediaQuery,useAppLifecycleState. - ποΈ Support Everywhere: Use hooks in
HookWidget,StatefulHookWidget, or viaHookBuilder. useSubscription: Tailored heavily toward bidirectional flows like WebSockets and GraphQL subscriptions. Automatically exposes the identical cache structures to queries but updates continuously via a native DartStreambacking.
Getting started #
Add just_hook to your pubspec.yaml:
dependencies:
just_hook: latest
Usage #
Extend HookWidget for your widget to use hooks.
Here's an example combining multiple hooks (useSearch and useFuture):
import 'package:flutter/material.dart';
import 'package:just_hook/just_hook.dart';
class MyHookPage extends HookWidget {
const MyHookPage({super.key});
@override
Widget build(BuildContext context) {
// Basic state hook
final counter = useState(0);
// Advanced search hook automatically gives controller and string text
final search = useSearch(initialText: 'Hooked Search');
// Mocks a stream ticking every second
final stream = useMemoized(() {
return Stream<int>.periodic(const Duration(seconds: 1), (i) => i).take(10);
}, []);
final streamSnapshot = useStream(stream);
// Mocks a future responding
final future = useMemoized(() {
return Future.delayed(const Duration(seconds: 2), () => 'Data Loaded!');
}, [counter.value]); // the future reloads when the counter increases
final futureSnapshot = useFuture(future);
return Scaffold(
appBar: AppBar(title: const Text('just_hook Examples')),
body: Center(
child: Column(
children: [
TextField(controller: search.controller),
Text('You typed: ${search.text}'),
Text('Stream Ticks: ${streamSnapshot.hasData ? streamSnapshot.data : "..."}'),
Text('Future Status: ${futureSnapshot.connectionState.name}')
],
),
),
);
}
}
How to create your own hook #
Hooks are objects that implement the Hook config and HookState behavior. Ensure you call use internally to register it to the current widget.
import 'package:just_hook/just_hook.dart';
int useMyHook() {
return use(const _MyHook());
}
class _MyHook extends Hook<int> {
const _MyHook();
@override
_MyHookState createState() => _MyHookState();
}
class _MyHookState extends HookState<int, _MyHook> {
@override
int build(BuildContext context) {
return 42;
}
}