Element.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #pragma once
  8. #include <functional>
  9. #include <memory>
  10. #include <react/core/ShadowNode.h>
  11. #include <react/element/ElementFragment.h>
  12. namespace facebook {
  13. namespace react {
  14. /*
  15. * `Element<>` is an abstraction layer that allows describing component
  16. * hierarchy in a declarative way. Creating `Element`s themself does not create
  17. * a component tree (aka `ShadowNode` tree) but describes some hierarchical
  18. * structure that might be used to build an actual component tree (similar to
  19. * XML Elements).
  20. * `Element` provides some basic type-safety guarantees: all modifications
  21. * of element objects require using objects (such as Props or State) of
  22. * compatible type.
  23. */
  24. template <typename ShadowNodeT>
  25. class Element final {
  26. public:
  27. using ConcreteProps = typename ShadowNodeT::ConcreteProps;
  28. using SharedConcreteProps = std::shared_ptr<ConcreteProps const>;
  29. using ConcreteState = typename ShadowNodeT::ConcreteState;
  30. using SharedConcreteState = std::shared_ptr<ConcreteState const>;
  31. using ConcreteShadowNode = ShadowNodeT;
  32. using ConcreteUnsharedShadowNode = std::shared_ptr<ConcreteShadowNode>;
  33. using ConcreteReferenceCallback =
  34. std::function<void(std::shared_ptr<ShadowNodeT const> const &shadowNode)>;
  35. /*
  36. * Constructs an `Element`.
  37. */
  38. Element() {
  39. fragment_.componentHandle = ShadowNodeT::Handle();
  40. fragment_.componentName = ShadowNodeT::Name();
  41. fragment_.props = ShadowNodeT::defaultSharedProps();
  42. }
  43. /*
  44. * Converts to `ElementFragment` object.
  45. */
  46. operator ElementFragment() {
  47. return fragment_;
  48. }
  49. /*
  50. * Sets `tag`.
  51. */
  52. Element &tag(Tag tag) {
  53. fragment_.tag = tag;
  54. return *this;
  55. }
  56. /*
  57. * Sets `surfaceId`.
  58. */
  59. Element &surfaceId(SurfaceId surfaceId) {
  60. fragment_.surfaceId = surfaceId;
  61. return *this;
  62. }
  63. /*
  64. * Sets `props`.
  65. */
  66. Element &props(SharedConcreteProps props) {
  67. fragment_.props = props;
  68. return *this;
  69. }
  70. /*
  71. * Sets `props` using callback.
  72. */
  73. Element &props(std::function<SharedConcreteProps()> callback) {
  74. fragment_.props = callback();
  75. return *this;
  76. }
  77. /*
  78. * Sets `state`.
  79. */
  80. Element &state(SharedConcreteState state) {
  81. fragment_.state = state;
  82. return *this;
  83. }
  84. /*
  85. * Sets `state` using callback.
  86. */
  87. Element &state(std::function<SharedConcreteState()> callback) {
  88. fragment_.state = state();
  89. return *this;
  90. }
  91. /*
  92. * Sets children.
  93. */
  94. Element &children(std::vector<ElementFragment> children) {
  95. auto fragments = ElementFragment::List{};
  96. fragments.reserve(children.size());
  97. for (auto const &child : children) {
  98. fragments.push_back(child);
  99. }
  100. fragment_.children = fragments;
  101. return *this;
  102. }
  103. /*
  104. * Calls the callback during component construction with a pointer to the
  105. * component which is being constructed.
  106. */
  107. Element &reference(
  108. std::function<void(ConcreteUnsharedShadowNode const &shadowNode)>
  109. callback) {
  110. fragment_.referenceCallback = callback;
  111. return *this;
  112. }
  113. /*
  114. * During component construction, assigns a given pointer to a component
  115. * that is being constructed.
  116. */
  117. Element &reference(ConcreteUnsharedShadowNode &outShadowNode) {
  118. fragment_.referenceCallback = [&](ShadowNode::Shared const &shadowNode) {
  119. outShadowNode = std::const_pointer_cast<ConcreteShadowNode>(
  120. std::static_pointer_cast<ConcreteShadowNode const>(shadowNode));
  121. };
  122. return *this;
  123. }
  124. /*
  125. * Calls the callback with a reference to a just constructed component.
  126. */
  127. Element &finalize(
  128. std::function<void(ConcreteShadowNode &shadowNode)> finalizeCallback) {
  129. fragment_.finalizeCallback = [=](ShadowNode &shadowNode) {
  130. return finalizeCallback(static_cast<ConcreteShadowNode &>(shadowNode));
  131. };
  132. return *this;
  133. }
  134. private:
  135. friend class ComponentBuilder;
  136. ElementFragment fragment_;
  137. };
  138. } // namespace react
  139. } // namespace facebook