Expand description
§Hooks
Hooks are special functions that must be called inside of Components.
These let you manage things like state or lifecycle of your component.
They are usually prefixed with use
, e.g use_animation
, use_signal
, use_effect
, use_memo
, etc.
§Rules of Hooks
Even though hooks appear to be normal functions they are in fact special so you cannot just call them however you want.
§1. They cannot be called conditionally
You cannot do the following because hooks need to maintain their order between multiple renders.
So, if the same component is calling 3 different hooks in the first render, and then in the next render if just calls 2, it would be breaking this rule.
❌:
#[component]
fn MyComponent(value: bool) -> Element {
let is_enabled = if value {
// This should be moved out of the conditional
let state = use_signal(|| value);
state()
} else {
true
};
Ok(VNode::placeholder())
}
✅:
#[component]
fn MyComponent(initial_value: bool) -> Element {
let is_enabled = use_signal(move || initial_value);
rsx!( label { "{is_enabled}" } )
}
Or even better, move the state up ✅:
#[component]
fn MyComponent(is_enabled: bool) -> Element {
rsx!( label { "{is_enabled}" } )
}
§2. They can only be called inside of Component functions
You cannot call them inside of event handlers, futures, etc.
❌:
#[component]
fn MyComponent() -> Element {
let onclick = |_| {
let state = use_signal(|| false);
};
rsx!(
label {
onclick,
"Hello, World!"
}
)
}
✅:
#[component]
fn MyComponent() -> Element {
let mut state = use_signal(|| false);
let onclick = move |_| {
state.set(true);
};
rsx!(
label {
onclick,
"Hello, World!"
}
)
}
§3. They cannot be called in loops
Hooks cannot be called in loops as the numbers of iterations might change between renders.
❌:
#[component]
fn MyComponent() -> Element {
for i in 0..5 {
let state = use_signal(|| i);
}
rsx!( label { "hi" } )
}
✅:
#[component]
fn MyComponent() -> Element {
let state = use_signal(|| (0..5).into_iter().collect::<Vec<_>>());
rsx!( label { "hi" } )
}