New implementation of handling didUpdateReactSubviews and didUpdateReactSubviews events

Summary:
Motivation:
* Current implementation of `didUpdateReactSubviews` relies on `processUpdatedProperties:parentProperties:` method of RCTShadowView, which we plan to remove.
* The existing implementation does not call handlers on unmounted nodes (because they are not part of traversing tree), which is not correct.
* The current implementation is tight with RCTComponentData, which is conceptually wrong, it should be a UIManager thing.
* The new implementation must be much more performant because of simplicity. (We can measure it only after removing `processUpdatedProperties`.)

Reviewed By: mmmulani

Differential Revision: D6595780

fbshipit-source-id: a517207c17b5d5db839c9ce99a37136292acf78c
This commit is contained in:
Valentin Shergin
2017-12-19 23:34:50 -08:00
committed by Facebook Github Bot
parent 4996b9aeb4
commit 7d1dedadd7
6 changed files with 102 additions and 26 deletions

View File

@@ -36,8 +36,6 @@ typedef void (^RCTBubblingEventBlock)(NSDictionary *body);
// View/ShadowView is a root view
- (BOOL)isReactRootView;
@optional
/**
* Called each time props have been set.
* Not all props have to be set - React can set only changed ones.

View File

@@ -355,10 +355,6 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
[props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id json, __unused BOOL *stop) {
[self propBlockForKey:key isShadowView:NO](view, json);
}];
if ([view respondsToSelector:@selector(didSetProps:)]) {
[view didSetProps:[props allKeys]];
}
}
- (void)setProps:(NSDictionary<NSString *, id> *)props forShadowView:(RCTShadowView *)shadowView
@@ -370,10 +366,6 @@ static RCTPropBlock createNSInvocationSetter(NSMethodSignature *typeSignature, S
[props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id json, __unused BOOL *stop) {
[self propBlockForKey:key isShadowView:YES](shadowView, json);
}];
if ([shadowView respondsToSelector:@selector(didSetProps:)]) {
[shadowView didSetProps:[props allKeys]];
}
}
- (NSDictionary<NSString *, id> *)viewConfig

View File

@@ -41,7 +41,6 @@ typedef NS_ENUM(unsigned int, meta_prop_t) {
BOOL _recomputePadding;
BOOL _recomputeMargin;
BOOL _recomputeBorder;
BOOL _didUpdateSubviews;
YGValue _paddingMetaProps[META_PROP_COUNT];
YGValue _marginMetaProps[META_PROP_COUNT];
YGValue _borderMetaProps[META_PROP_COUNT];
@@ -263,19 +262,6 @@ static void RCTProcessMetaPropsBorder(const YGValue metaProps[META_PROP_COUNT],
- (NSDictionary<NSString *, id> *)processUpdatedProperties:(NSMutableSet<RCTApplierBlock> *)applierBlocks
parentProperties:(NSDictionary<NSString *, id> *)parentProperties
{
// TODO: we always refresh all propagated properties when propagation is
// dirtied, but really we should track which properties have changed and
// only update those.
if (_didUpdateSubviews) {
_didUpdateSubviews = NO;
[self didUpdateReactSubviews];
[applierBlocks addObject:^(NSDictionary<NSNumber *, UIView *> *viewRegistry) {
UIView *view = viewRegistry[self->_reactTag];
[view didUpdateReactSubviews];
}];
}
return parentProperties;
}
@@ -435,7 +421,6 @@ static void RCTProcessMetaPropsBorder(const YGValue metaProps[META_PROP_COUNT],
YGNodeInsertChild(_yogaNode, subview.yogaNode, (uint32_t)atIndex);
}
subview->_superview = self;
_didUpdateSubviews = YES;
[self dirtyText];
[self dirtyPropagation];
}
@@ -444,7 +429,6 @@ static void RCTProcessMetaPropsBorder(const YGValue metaProps[META_PROP_COUNT],
{
[subview dirtyText];
[subview dirtyPropagation];
_didUpdateSubviews = YES;
subview->_superview = nil;
[_reactSubviews removeObject:subview];
if (![self isYogaLeafNode]) {

View File

@@ -60,6 +60,12 @@
*/
- (void)didUpdateReactSubviews;
/**
* Called each time props have been set.
* The default implementation does nothing.
*/
- (void)didSetProps:(NSArray<NSString *> *)changedProps;
/**
* Used by the UIIManager to set the view frame.
* May be overriden to disable animation, etc.

View File

@@ -172,6 +172,11 @@
}
}
- (void)didSetProps:(__unused NSArray<NSString *> *)changedProps
{
// The default implementation does nothing.
}
- (void)reactSetFrame:(CGRect)frame
{
// These frames are in terms of anchorPoint = topLeft, but internally the