hooks_bad.rs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #![allow(non_snake_case)]
  2. use dioxus::prelude::*;
  3. use std::collections::HashMap;
  4. fn main() {
  5. dioxus_desktop::launch(App);
  6. }
  7. #[rustfmt::skip]
  8. fn App(cx: Scope) -> Element {
  9. let you_are_happy = true;
  10. let you_know_it = false;
  11. // ANCHOR: conditional
  12. // ❌ don't call hooks in conditionals!
  13. // We must ensure that the same hooks will be called every time
  14. // But `if` statements only run if the conditional is true!
  15. // So we might violate rule 2.
  16. if you_are_happy && you_know_it {
  17. let something = use_state(cx, || "hands");
  18. println!("clap your {something}")
  19. }
  20. // ✅ instead, *always* call use_state
  21. // You can put other stuff in the conditional though
  22. let something = use_state(cx, || "hands");
  23. if you_are_happy && you_know_it {
  24. println!("clap your {something}")
  25. }
  26. // ANCHOR_END: conditional
  27. // ANCHOR: closure
  28. // ❌ don't call hooks inside closures!
  29. // We can't guarantee that the closure, if used, will be called in the same order every time
  30. let _a = || {
  31. let b = use_state(cx, || 0);
  32. b.get()
  33. };
  34. // ✅ instead, move hook `b` outside
  35. let b = use_state(cx, || 0);
  36. let _a = || b.get();
  37. // ANCHOR_END: closure
  38. let names: Vec<&str> = vec![];
  39. // ANCHOR: loop
  40. // `names` is a Vec<&str>
  41. // ❌ Do not use hooks in loops!
  42. // In this case, if the length of the Vec changes, we break rule 2
  43. for _name in &names {
  44. let is_selected = use_state(cx, || false);
  45. println!("selected: {is_selected}");
  46. }
  47. // ✅ Instead, use a hashmap with use_ref
  48. let selection_map = use_ref(cx, HashMap::<&str, bool>::new);
  49. for name in &names {
  50. let is_selected = selection_map.read()[name];
  51. println!("selected: {is_selected}");
  52. }
  53. // ANCHOR_END: loop
  54. cx.render(rsx!(()))
  55. }