mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
0127501dbf
Improve inline docs * improve incorrect event handler return error message * Improve event handler docs * document the eval functions * document spawn and common spawn errors * fix event handler docs * add notes about how you use attributes and elements in rsx * add doc aliases for attributes and events we rename * add some more aliases for common search terms * don't doc ignore any public examples in core * don't ignore public doc examples in ssr * don't ignore examples in the dioxus package readme * add a warning when you launch without a renderer enabled * fix some outdated element docs * add a bunch of examples to resource * add notes about desktop events * add more docs for use_resource * add on_unimplemented hint to Dependency * fix some unresolved links * add examples to each of the router traits * add not implemented errors for router traits * add an example to the routable trait * expand rsx macro docs * improve memo docs * update the dioxus readme * mention dioxus crate features in the docs * fix a bunch of doc tests * fix html doc tests * fix router doc tests * fix dioxus signals doc tests * fix dioxus ssr doc tests * fix use_future example in the hooks cheat sheet * add a javascript alias for eval * fix hook explanation values * remove unused embed-doc-image dependency
152 lines
4.3 KiB
Markdown
152 lines
4.3 KiB
Markdown
## Additional Information that may be useful
|
|
|
|
<details>
|
|
<summary>This function is a hook which means you need to <b>follow the rules of hooks</b> when you call it. You can click here to learn more about the rules of hooks.</summary>
|
|
|
|
Hooks in dioxus need to run in the same order every time you run the component. To make sure you run hooks in a consistent order, you should follow the rules of hooks:
|
|
|
|
1. Hooks should only be called from the root of a component or another hook
|
|
|
|
```rust
|
|
# use dioxus::prelude::*;
|
|
fn App() -> Element {
|
|
// ✅ You can call hooks from the body of a component
|
|
let number = use_signal(|| 1);
|
|
if number() == 1 {
|
|
// ❌ You can run into issues if you can hooks inside other expressions inside your component
|
|
// If number changes from 0 to 1, the order of the hooks will be different and your app may panic
|
|
let string = use_signal(|| "hello world".to_string());
|
|
}
|
|
|
|
todo!()
|
|
}
|
|
|
|
fn use_my_hook() -> Signal<i32> {
|
|
// ✅ You can call hooks from the body of other hooks
|
|
let number = use_signal(|| 1);
|
|
// ❌ Again, creating hooks inside expressions inside other hooks can cause issues
|
|
if number() == 1 {
|
|
let string = use_signal(|| "hello world".to_string());
|
|
}
|
|
|
|
number
|
|
}
|
|
```
|
|
|
|
2. Hooks should always start with `use_` to make it clear that you need to call them in a consistent order
|
|
|
|
Because hooks should only be called from the root of a component or another hook, you shouldn't call hooks inside of:
|
|
|
|
- ❌ Conditionals
|
|
|
|
```rust
|
|
# use dioxus::prelude::*;
|
|
fn App() -> Element {
|
|
let number = use_signal(|| 1);
|
|
// ❌ Changing the condition will change the order of the hooks
|
|
if number() == 1 {
|
|
let string = use_signal(|| "hello world".to_string());
|
|
}
|
|
|
|
// ❌ Changing the value you are matching will change the order of the hooks
|
|
match number() {
|
|
1 => {
|
|
let string = use_signal(|| "hello world".to_string());
|
|
},
|
|
_ => (),
|
|
}
|
|
|
|
todo!()
|
|
}
|
|
```
|
|
|
|
- ❌ Loops
|
|
|
|
```rust
|
|
# use dioxus::prelude::*;
|
|
fn App() -> Element {
|
|
let number = use_signal(|| 1);
|
|
// ❌ Changing the loop will change the order of the hooks
|
|
for i in 0..number() {
|
|
let string = use_signal(|| "hello world".to_string());
|
|
}
|
|
|
|
todo!()
|
|
}
|
|
```
|
|
|
|
- ❌ Event Handlers
|
|
|
|
```rust
|
|
# use dioxus::prelude::*;
|
|
fn App() -> Element {
|
|
rsx! {
|
|
button {
|
|
onclick: move |_| {
|
|
// ❌ Calling the event handler will change the order of the hooks
|
|
use_signal(|| "hello world".to_string());
|
|
},
|
|
"Click me"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
- ❌ Initialization closures in other hooks
|
|
|
|
```rust
|
|
# use dioxus::prelude::*;
|
|
fn App() -> Element {
|
|
let number = use_signal(|| {
|
|
// ❌ This closure will only be called when the component is first created. Running the component will change the order of the hooks
|
|
let string = use_signal(|| "hello world".to_string());
|
|
string()
|
|
});
|
|
|
|
todo!()
|
|
}
|
|
```
|
|
|
|
<details>
|
|
<summary>Why do hooks need to run in a consistent order?</summary>
|
|
|
|
Hooks need to be run in a consistent order because dioxus stores hooks in a list and uses the order you run hooks in to determine what part of the state belongs to which hook.
|
|
|
|
Lets look at an example component:
|
|
|
|
```rust
|
|
# use dioxus::prelude::*;
|
|
fn App() -> Element {
|
|
let number = use_signal(|| 1); // Hook 1
|
|
let string = use_signal(|| "hello world".to_string()); // Hook 2
|
|
let doubled = use_memo(move || number() * 2); // Hook 3
|
|
|
|
todo!()
|
|
}
|
|
```
|
|
|
|
When we first create the component, we run the hooks in the order they are defined and store the state in the component in a list.
|
|
|
|
```rust, ignore
|
|
[
|
|
Box::new(1),
|
|
Box::new("hello world".to_string()),
|
|
Box::new(2),
|
|
]
|
|
```
|
|
|
|
Next time we run the component, we return items from the state list instead of creating state again.
|
|
|
|
```rust, ignore
|
|
[
|
|
Box::new(1), // Hook 1 returns 1
|
|
Box::new("hello world".to_string()), // Hook 2 returns "hello world"
|
|
Box::new(2), // Hook 3 returns 2
|
|
]
|
|
```
|
|
|
|
The order the hooks are run it must be the same because the order determines which hook gets what state! If you run the hooks in a different order, dioxus may panic because it can't turn the state back into the right type or you may just get the wrong state for your hook.
|
|
|
|
</details>
|
|
|
|
</details>
|