You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Context: I’m working on a list virtualization library (azimgd/shadowlist), which works as follows:
Takes JSON data and a template from the renderItem prop.
Loops over the data items, building a shadow node by replacing {{index.key}} string in jsx with data[index].key in native (similar to how the Jinja templates work).
Caches shadow nodes that have already been laid out.
Only displays the list items that fit within the current viewport.
Synchronizing nativeTag Between JS and Native
React increments the nativeTag by 2 for each UIManager::createNode.
nextFamilyTag += 2;
autoconst family = componentDescriptor.createFamily({nextFamilyTag, shadowNode->getSurfaceId(), instanceHandle});
Is there a way to sync these values between JS and Native without causing tag collisions? Setting the initial tag to 0 will obviously cause a duplicate and trigger this error:
Thread 1: "RCTComponentViewRegistry: Attempt to dequeue already registered component."
I tried to fix this by decrementing the tag by 2, starting from a negative number (based on this implementation: Link (Shoutout to Margelo and @janicduplessis for opensourcing Wishlist). But this caused some issues on iOS, like blocked events (e.g., onTouch) for certain items.
Setting a large offset (like nativeTag = 500k) fixed the issue on iOS, but I still need to look into the Android side.
createNode(500000)
createNode(500002)
...
Accessing rawProps on iOS
It’s really convenient to iterate over a folly::dynamic object and set properties using object[key] = value without having to cast node props. But the getProps()→rawProps method is only available on Android. Is there any other way to achieve this on iOS?
My goal is to have a generic props replace function instead of doing:
// https://github.com/azimgd/shadowlist/blob/ce75d85e63a5d9830b5757284dd72aeafcbabf20/cpp/react/renderer/components/RNShadowlistSpec/SLTemplate.cpp#L20staticvoidupdateRawTextProps(const SLContainerProps::SLContainerDataItem &elementData, const std::shared_ptr<ShadowNode> &nextShadowNode, const ShadowNode::Shared &shadowNode) {
if (shadowNode->getComponentName() != std::string("RawText")) {
return;
}
// replacing {{index.key}} string from jsx with data[index].key on RawText instance
RawTextShadowNode::ConcreteProps* updatedProps = const_cast<RawTextShadowNode::ConcreteProps*>(
static_cast<const RawTextShadowNode::ConcreteProps*>(nextShadowNode->getProps().get()));
auto path = SLKeyExtractor::extractKey(updatedProps->text);
updatedProps->text = SLContainerProps::getElementValueByPath(elementData, path);
}
InstanceHandle Creation
On Android, the event emitter seems to be turned off for some items. This means the onPress callback will work for some items, but not for others. I want to double-check that I'm following the correct approach for instance creation here. Related issue description.
While current approach works just fine on iOS, Android is generating error logs which might also be related to the next point:
Su...ingManager shadowlist.example E removeViewAt: [525570] -> [46] @1: view already removed from parent! Children in parent: 1
Su...ingManager shadowlist.example E removeViewAt: [525590] -> [46] @1: view already removed from parent! Children in parent: 1
...
Managing Layout Items
Is this the right way to manually manage the children of a component?
I assumed that each call to updateState() would automatically trigger the ConcreteShadowNode::layout function. However, it doesn't seem to do so unless I explicitly call yogaNode_.setDirty(true) within the layout function. While ConcreteComponentDescriptor::adopt is triggered, the layout doesn't update automatically. Is this the expected behavior?
// SLContainerShadowNode.cppvoidSLContainerShadowNode::layout(LayoutContext layoutContext) {
// Layout will not be triggered unless this is called
yogaNode_.setDirty(true)
}
// Adopt is triggered on each state update, as expectedclassSLContainerComponentDescriptor : publicConcreteComponentDescriptor<SLContainerShadowNode> {
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
voidadopt(ShadowNode& shadowNode) constoverride {
ConcreteComponentDescriptor::adopt(shadowNode);
}
};
// SLContainer.mm
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
auto scrollPosition = RCTPointFromCGPoint(scrollView.contentOffset);
_state->updateState([scrollPosition](const SLContainerShadowNode::ConcreteState::Data &data) {
auto newData = data;
newData.scrollPosition = scrollPosition;
return std::make_shared<const SLContainerShadowNode::ConcreteState::Data>(newData);
});
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Context: I’m working on a list virtualization library (azimgd/shadowlist), which works as follows:
{{index.key}}
string in jsx withdata[index].key
in native (similar to how the Jinja templates work).Synchronizing nativeTag Between JS and Native
React increments the nativeTag by 2 for each
UIManager::createNode
.Is there a way to sync these values between JS and Native without causing tag collisions? Setting the initial tag to 0 will obviously cause a duplicate and trigger this error:
Shadownode creation
I tried to fix this by decrementing the tag by 2, starting from a negative number (based on this implementation: Link (Shoutout to Margelo and @janicduplessis for opensourcing Wishlist). But this caused some issues on iOS, like blocked events (e.g., onTouch) for certain items.
Setting a large offset (like nativeTag = 500k) fixed the issue on iOS, but I still need to look into the Android side.
Accessing rawProps on iOS
It’s really convenient to iterate over a folly::dynamic object and set properties using object[key] = value without having to cast node props. But the getProps()→rawProps method is only available on Android. Is there any other way to achieve this on iOS?
My goal is to have a generic props replace function instead of doing:
InstanceHandle Creation
On Android, the event emitter seems to be turned off for some items. This means the
onPress
callback will work for some items, but not for others. I want to double-check that I'm following the correct approach for instance creation here. Related issue description.While current approach works just fine on iOS, Android is generating error logs which might also be related to the next point:
Managing Layout Items
Is this the right way to manually manage the children of a component?
State updates
I assumed that each call to
updateState()
would automatically trigger theConcreteShadowNode::layout
function. However, it doesn't seem to do so unless I explicitly callyogaNode_.setDirty(true)
within the layout function. WhileConcreteComponentDescriptor::adopt
is triggered, the layout doesn't update automatically. Is this the expected behavior?@cipolleschi @cortinico It would be a great help if you could assist.
Beta Was this translation helpful? Give feedback.
All reactions