react_hooks 1.0.0
react_hooks: ^1.0.0 copied to clipboard
A Flutter package that provides React-like hooks (useState, useEffect) for state management and side effects in Flutter apps.
React Hooks for Flutter #
A Flutter package that brings React Hooks-like state management and side effect handling to Flutter, enabling you to write React-style functional components in Flutter.
Features #
- 🚀 useState: React-like state management with multiple syntax styles
- ⚡ useEffect: Side effect handling and lifecycle management
- 🎯 useMemo: Cache expensive computations
- 🔄 useCallback: Cache callback functions
- 🌐 useContext: Context state sharing
- 🧹 Auto Cleanup: Automatic side effect cleanup
- 💡 HookWidget: React functional component-like base class
- 🎨 Multiple Syntax: Support property access, destructuring, tuple and more syntax styles
Installation #
Add this to your pubspec.yaml
file:
dependencies:
react_hooks: ^1.0.0
Then run:
flutter pub get
Quick Start #
Basic Usage #
import 'package:flutter/material.dart';
import 'package:react_hooks/react_hooks.dart';
class CounterApp extends HookWidget {
@override
Widget build(BuildContext context) {
// 🎉 Completely React-like syntax!
final countState = useState(0);
final nameState = useState<String>('Flutter');
// useEffect - Execute once when component mounts
useEffect(() {
print('Component mounted');
return () => print('Component will unmount');
}, []);
// useEffect - Listen to state changes
useEffect(() {
print('Count changed: ${countState.value}');
return null;
}, [countState.value]);
return Scaffold(
appBar: AppBar(title: Text('${nameState.value} Counter')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Count: ${countState.value}'),
ElevatedButton(
onPressed: () => countState.setValue(countState.value + 1),
child: Text('Increment'),
),
],
),
),
);
}
}
useContext State Sharing #
// 1. Define Context value type
class CounterContextValue {
final int count;
final void Function() increment;
CounterContextValue({required this.count, required this.increment});
}
// 2. Custom Hook
CounterContextValue useCounter([int initialValue = 0]) {
final countState = useState(initialValue);
void increment() => countState.update((prev) => prev + 1);
return CounterContextValue(
count: countState.value,
increment: increment,
);
}
// 3. Provider component
class App extends HookWidget {
@override
Widget build(BuildContext context) {
return HookProvider<CounterContextValue>(
create: () => useCounter(0), // Inject custom hook in Provider
child: Column(
children: [
HeaderComponent(), // Parent component - display title only
CounterDisplay(), // Child component - get state via Context
CounterControls(), // Child component - control state via Context
],
),
);
}
}
// 4. Child components use useContext to get shared state
class CounterDisplay extends HookWidget {
@override
Widget build(BuildContext context) {
final counter = useContext<CounterContextValue>(context);
return Text('Count: ${counter.count}');
}
}
class CounterControls extends HookWidget {
@override
Widget build(BuildContext context) {
final counter = useContext<CounterContextValue>(context);
return ElevatedButton(
onPressed: counter.increment,
child: Text('Increment'),
);
}
}
API Reference #
useState #
Creates a state hook that returns an object containing the current value and setter function.
final countState = useState(0);
// Multiple access ways
countState.value // Get value
countState.setValue(10) // Set value
countState.update((prev) => prev + 1) // Functional update
useEffect(EffectCallback effect, [Dependencies? dependencies]) #
Handle side effects, similar to React's useEffect.
// Execute once on component mount
useEffect(() {
print('Component mounted');
return () => print('Cleanup');
}, []);
// Listen to specific state changes
useEffect(() {
print('Count: ${countState.value}');
return null;
}, [countState.value]);
useContext #
Get shared state from Context.
final appState = useContext<AppContextValue>(context);
Convenient Hook Variants #
final boolState = useBool(false); // Boolean value, supports toggle()
final textController = useTextEditingController('initial'); // TextField controller
Example Project #
See the example/
directory for complete sample code, including:
- Basic useState examples
- Complex examples combining useContext with custom hooks
- Demonstrations of multiple syntax styles
License #
MIT License
Contributing #
Pull requests and issues are welcome!