component.rs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. //! This file handles the supporting infrastructure for the `Component` trait and `Properties` which makes it possible
  2. //! for components to be used within Nodes.
  3. //!
  4. //! Note - using the builder pattern does not required the Properties trait to be implemented - the only thing that matters is
  5. //! if the type suppports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
  6. //! that ensures compile-time required and optional fields on cx.
  7. use crate::innerlude::FC;
  8. pub trait Properties: Sized {
  9. type Builder;
  10. fn builder() -> Self::Builder;
  11. /// Memoization can only happen if the props are 'static
  12. /// The user must know if their props are static, but if they make a mistake, UB happens
  13. /// Therefore it's unsafe to memeoize.
  14. unsafe fn memoize(&self, other: &Self) -> bool;
  15. }
  16. impl Properties for () {
  17. type Builder = EmptyBuilder;
  18. fn builder() -> Self::Builder {
  19. EmptyBuilder {}
  20. }
  21. unsafe fn memoize(&self, _other: &Self) -> bool {
  22. true
  23. }
  24. }
  25. // We allow components to use the () generic parameter if they have no props. This impl enables the "build" method
  26. // that the macros use to anonymously complete prop construction.
  27. pub struct EmptyBuilder;
  28. impl EmptyBuilder {
  29. #[inline]
  30. pub fn build(self) -> () {
  31. ()
  32. }
  33. }
  34. /// This utility function launches the builder method so rsx! and html! macros can use the typed-builder pattern
  35. /// to initialize a component's props.
  36. pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
  37. T::builder()
  38. }
  39. /// Create inline fragments
  40. /// --
  41. ///
  42. /// Fragments capture a series of children without rendering extra nodes.
  43. ///
  44. /// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
  45. /// Try to avoid nesting fragments if you can. Infinitely nested Fragments *will* cause diffing to crash.
  46. #[allow(non_upper_case_globals)]
  47. pub const Fragment: FC<()> = |cx| {
  48. use crate::prelude::*;
  49. cx.render(LazyNodes::new(move |c| {
  50. crate::nodebuilder::vfragment(c, None, cx.children())
  51. }))
  52. };