Introduce Element<>.stateData API

Summary:
Changelog: [Internal]

Previous interface `Element<>.state` wasn't usable because creating ConcreteState  requires ownership of component descriptor and family. Family isn't created until later and it isn't accessible to the caller.

To work around this shortcoming, we create `stateData` rather than state.

Reviewed By: JoshuaGross

Differential Revision: D23028296

fbshipit-source-id: fba35ea8e6986b77379b1dddaa37012f4234f86e
This commit is contained in:
Samuel Susla
2020-08-10 12:52:22 -07:00
committed by Facebook GitHub Bot
parent 8d6b41e9bc
commit 6db19b036e
3 changed files with 21 additions and 15 deletions
@@ -30,10 +30,8 @@ ShadowNode::Unshared ComponentBuilder::build(
elementFragment.tag, elementFragment.surfaceId, nullptr},
nullptr);
auto state = elementFragment.state
? elementFragment.state
: componentDescriptor.createInitialState(
ShadowNodeFragment{elementFragment.props}, family);
auto state = componentDescriptor.createInitialState(
ShadowNodeFragment{elementFragment.props}, family);
auto constShadowNode = componentDescriptor.createShadowNode(
ShadowNodeFragment{
@@ -42,6 +40,16 @@ ShadowNode::Unshared ComponentBuilder::build(
state},
family);
if (elementFragment.stateCallback) {
auto newState = componentDescriptor.createState(
*family, elementFragment.stateCallback());
constShadowNode = componentDescriptor.cloneShadowNode(
*constShadowNode,
ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(),
ShadowNodeFragment::childrenPlaceholder(),
newState});
}
auto shadowNode = std::const_pointer_cast<ShadowNode>(constShadowNode);
if (elementFragment.referenceCallback) {
+7 -10
View File
@@ -33,6 +33,7 @@ class Element final {
using ConcreteProps = typename ShadowNodeT::ConcreteProps;
using SharedConcreteProps = std::shared_ptr<ConcreteProps const>;
using ConcreteState = typename ShadowNodeT::ConcreteState;
using ConcreteStateData = typename ShadowNodeT::ConcreteStateData;
using SharedConcreteState = std::shared_ptr<ConcreteState const>;
using ConcreteShadowNode = ShadowNodeT;
using ConcreteUnsharedShadowNode = std::shared_ptr<ConcreteShadowNode>;
@@ -88,19 +89,15 @@ class Element final {
return *this;
}
/*
* Sets `state`.
*/
Element &state(SharedConcreteState state) {
fragment_.state = state;
return *this;
}
/*
* Sets `state` using callback.
*/
Element &state(std::function<SharedConcreteState()> callback) {
fragment_.state = state();
Element &stateData(std::function<void(ConcreteStateData&)> callback) {
fragment_.stateCallback = [&]() -> StateData::Shared {
auto stateData = ConcreteStateData();
callback(stateData);
return std::make_shared<ConcreteStateData>(stateData);
};
return *this;
}
@@ -30,6 +30,7 @@ class ElementFragment final {
using ReferenceCallback =
std::function<void(ShadowNode::Unshared const &shadowNode)>;
using FinalizeCallback = std::function<void(ShadowNode &shadowNode)>;
using StateCallback = std::function<StateData::Shared()>;
/*
* ComponentDescriptor part (describes the type)
@@ -47,7 +48,6 @@ class ElementFragment final {
* ShadowNode part (describes the instance)
*/
Props::Shared props;
State::Shared state;
List children;
/*
@@ -55,6 +55,7 @@ class ElementFragment final {
*/
ReferenceCallback referenceCallback;
FinalizeCallback finalizeCallback;
StateCallback stateCallback;
};
} // namespace react