docs: add rules of hooks
This commit is contained in:
1 parent
4fb2221ee1
commit
564284f4be
5 files changed
+113
-9
No files matched your search
@@ -76,6 +76,78 @@ This is why hooks called out of order will fail - if we try to downcast a `Hook<
|
||||
|
||||
This pattern might seem strange at first, but it can be a significant upgrade over structs as blobs of state, which tend to be difficult to use in [Rust given the ownership system](https://rust-lang.github.io/rfcs/2229-capture-disjoint-fields.html).
|
||||
|
||||
|
||||
## Rules of hooks
|
||||
|
||||
Hooks are sensitive to how they are used. To use hooks, you must abide by the
|
||||
"rules of hooks" (borrowed from react)](https://reactjs.org/docs/hooks-rules.html):
|
||||
|
||||
- Functions with "use_" should not be called in callbacks
|
||||
- Functions with "use_" should not be called out of order
|
||||
- Functions with "use_" should not be called in loops or conditionals
|
||||
|
||||
Examples of "no-nos" include:
|
||||
|
||||
### ❌ Nested uses
|
||||
|
||||
```rust
|
||||
// ❌ don't call use_hook or any `use_` function *inside* use_hook!
|
||||
cx.use_hook(|_| {
|
||||
let name = cx.use_hook(|_| "ads");
|
||||
})
|
||||
|
||||
// ✅ instead, move the first hook above
|
||||
let name = cx.use_hook(|_| "ads");
|
||||
cx.use_hook(|_| {
|
||||
// do something with name here
|
||||
})
|
||||
```
|
||||
|
||||
### ❌ Uses in conditionals
|
||||
```rust
|
||||
// ❌ don't call use_ in conditionals!
|
||||
if do_thing {
|
||||
let name = use_state(&cx, || 0);
|
||||
}
|
||||
|
||||
// ✅ instead, *always* call use_state but leave your logic
|
||||
let name = use_state(&cx, || 0);
|
||||
if do_thing {
|
||||
// do thing with name here
|
||||
}
|
||||
```
|
||||
|
||||
### ❌ Uses in loops
|
||||
|
||||
|
||||
```rust
|
||||
// ❌ Do not use hooks in loops!
|
||||
let mut nodes = vec![];
|
||||
|
||||
for name in names {
|
||||
let age = use_state(&cx, |_| 0);
|
||||
nodes.push(cx.render(rsx!{
|
||||
div { "{age}" }
|
||||
}))
|
||||
}
|
||||
|
||||
// ✅ Instead, consider refactoring your usecase into components
|
||||
#[inline_props]
|
||||
fn Child(cx: Scope, name: String) -> Element {
|
||||
let age = use_state(&cx, |_| 0);
|
||||
cx.render(rsx!{ div { "{age}" } })
|
||||
}
|
||||
|
||||
// ✅ Or, use a hashmap with use_ref
|
||||
```rust
|
||||
let ages = use_ref(&cx, |_| HashMap::new());
|
||||
|
||||
names.iter().map(|name| {
|
||||
let age = ages.get(name).unwrap();
|
||||
cx.render(rsx!{ div { "{age}" } })
|
||||
})
|
||||
```
|
||||
|
||||
## Building new Hooks
|
||||
|
||||
However, most hooks you'll interact with *don't* return an `&mut T` since this is not very useful in a real-world situation.
|
||||
@@ -168,6 +240,7 @@ fn example(cx: Scope) -> Element {
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Hooks provided by the `Dioxus-Hooks` package
|
||||
|
||||
By default, we bundle a handful of hooks in the Dioxus-Hooks package. Feel free to click on each hook to view its definition and associated documentation.
|
||||
|
||||
Reference in new issue
Block a user