Saltearse al contenido

RtHook

Esta página aún no está disponible en tu idioma.

RtHook is a class that provides a way to create a custom hook.

Syntax

abstract class RtHook with RtState<RtHook> {
static get $register => HookBindingZone<RtHook>();
HookBindingZone<RtHook> get $;
void initHook()
void update([Function()? fnUpdate])
}

Properties & Methods

  • $register: A static getter to allow access to HookBindingZone . It’s responsible for registering a RtHook and attaching collected states to it.

  • $: A required getter to access the HookBindingZone instance. It must be defined has a final property on first line of the class for registering the hook and attach the states below it, like this:

    final $ = RtHook.$register;
  • initHook : Called when the hook is initialized. Useful for setting up state dependencies or performing side effects when the hook is first created.

Properties and methods inherited from RtState
  • debugLabel: A string that represents the label of the state object for debugging purposes.
  • debugInfo: A map that contains debug information about the state object.
  • update : Executes a callback function and notify its observers that the state has changed. When it is invoked, it emits two lifecycle events to signal the state transition:
    • Lifecycle.willUpdate is emitted first, indicating the impending update.
    • Lifecycle.didUpdate is emitted once the update process is complete.
  • notify : Forces the state to notify its observers. Unlike update , it emits only the Lifecycle.didUpdate event, as it doesn’t involve any preparatory steps before the notification.
  • bind : Establishes a connection between the state and a specific instance. This connection allows the instance to reactively update based on changes to the state. By binding the state, the instance becomes aware of changes to the state and can appropriately reflect those changes in its behavior.
  • unbind : Releases the connection between the state and the instance. When unbinding, the instance will no longer receive updates from the state. This can be useful when an instance is no longer actively using the state or when it needs to detach from the state temporarily or permanently.
  • dispose : Is responsible for cleaning up the state and any associated observers or resources. Disposing of the state ensures that it is properly released and no longer consumes memory or processing resources unnecessarily.

Usage

Creating a custom hook

To create a custom hook, you need to create a class that extends RtHook and follow the naming convention with the Use prefix.

Here’s an example of a custom hook that manages the state of a text input:

1
import 'package:reactter/reactter.dart';
2
import 'package:flutter/widgets.dart';
3
4
class UseTextInput extends RtHook {
5
// This line is REQUIRED!
6
final $ = RtHook.$register;
7
8
final controller = TextEditingController();
9
10
String _value = '';
11
String? get value => _value;
12
13
@override
14
initHook() {
15
UseEffect(() {
16
controller.addListener(() {
17
update(() => _value = controller.text);
18
});
19
20
return controller.dispose;
21
}, []);
22
}
23
}

As shown in the example above, we can utilize other hooks such as UseEffect to monitor changes in the text input’s controller and ensure it is disposed when the hook is destroyed.

The update method is used to set the internal _value to the current text in the controller, which keeps the state synchronized with the input. This methods is a part of the RtHook class that allows you to update the state of the hook.

Using the hook

You can then call that custom hook from anywhere in the code and get access to its shared logic:

1
import 'package:flutter_reactter/flutter_reactter.dart';
2
import 'use_text_input.dart';
3
4
class MyController {
5
final firstNameInput = UseTextInput();
6
final lastNameInput = UseTextInput();
7
8
late final fullName = Rt.lazyState(
9
() => UseCompute(
10
() {
11
final firstName = firstNameInput.value;
12
final lastName = lastNameInput.value;
13
14
return "$firstName $lastName";
15
},
16
[firstNameInput, lastNameInput],
17
),
18
this,
19
);
20
}
1
import 'package:flutter/material.dart';
2
import 'package:flutter_reactter/flutter_reactter.dart';
3
import 'my_controller.dart';
4
5
class MyCustomForm extends StatelessWidget {
6
const MyCustomForm({Key? key}) : super(key: key);
7
8
@override
9
Widget build(BuildContext context) {
10
return RtProvider<MyController>(
11
() => MyController(),
12
builder: (context, myController, child) {
13
return Scaffold(
14
appBar: AppBar(
15
title: const Text("Custom hook example"),
16
),
17
body: Padding(
18
padding: const EdgeInsets.all(16),
19
child: Column(
20
crossAxisAlignment: CrossAxisAlignment.start,
21
children: [
22
RtConsumer<MyController>(
23
listenStates: (myController) => [myController.fullName],
24
child: const Text(
25
"Full Name:",
26
style: TextStyle(fontWeight: FontWeight.bold),
27
),
28
builder: (context, myController, child) {
29
return Row(
30
children: [
31
child!,
32
const SizedBox(width: 4),
33
Text(myController.fullName.value),
34
],
35
);
36
},
37
),
38
const SizedBox(height: 8),
39
TextField(
40
decoration: InputDecoration(
41
hintText: "First Name",
42
),
43
controller: myController.firstNameInput.controller,
44
),
45
TextField(
46
decoration: InputDecoration(
47
hintText: "Last Name",
48
),
49
controller: myController.lastNameInput.controller,
50
),
51
],
52
),
53
),
54
);
55
},
56
);
57
}
58
}
1
import 'package:reactter/reactter.dart';
2
import 'package:flutter/widgets.dart';
3
4
class UseTextInput extends RtHook {
5
// This line is REQUIRED!
6
final $ = RtHook.$register;
7
8
final controller = TextEditingController();
9
10
String _value = '';
11
String? get value => _value;
12
13
@override
14
initHook() {
15
UseEffect(() {
16
controller.addListener(() {
17
update(() => _value = controller.text);
18
});
19
20
return controller.dispose;
21
}, []);
22
}
23
}
1
import 'package:flutter/material.dart';
2
import 'my_custom_form.dart';
3
4
void main() {
5
runApp(MyApp());
6
}
7
8
class MyApp extends StatelessWidget {
9
@override
10
Widget build(BuildContext context) {
11
return MaterialApp(
12
home: MyCustomForm(),
13
);
14
}
15
}

In the previous example, the form captures the input from the name and surname fields, combines them into a full name, and displays the result. The MyController component uses the UseTextInput hook (custom hook created previously) to manage the name and lastname inputs.

The fullName state is defined using UseCompute , which calculates the full name based on the values of firstNameInput and lastNameInput. This ensures that the full name updates automatically whenever either input changes.