Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update layout props without crossing JS bridge #45

Merged
merged 48 commits into from
Aug 14, 2018

Conversation

osdnk
Copy link
Contributor

@osdnk osdnk commented Aug 1, 2018

Motivation

The problem occurs if we wish to update props which are not supported natively to be modifier via Aniamted.Value. It refers to props like top, width etc.

Changes

Initially wish to add handling for greater number of properties in RN core which came out to be quite difficult and I gave up with this idea.
The another approach I decided to try was to use flow of updating properties from JS, but call them from native code.
Before these changes the flow was:

Changing property not supported natively e.g. width:

  1. Animated Value is being changes as result of animation

image

The bias of passing bridge seems to be extremely useless and therefore I managed to omit it.

now it looks more or less like:

image

@osdnk osdnk changed the title Add updating jsPriops withour using bridre Add updating jsProps without using bridge Aug 1, 2018
@kmagiera kmagiera changed the title Add updating jsProps without using bridge Update layout props without crossing JS bridge Aug 2, 2018
};

function configureJSPropsHandledNatively() {
ReanimatedModule.configureJSPropsHandledNatively(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets move this to a common method that would take both lists at once

@@ -35,3 +35,74 @@ export function addWhitelistedNativeProps(props) {
}

configureNativeProps();

const JS_PROPS_HANDLED_NATIVELY_WHITELIST = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment:

Whitelist of view props that can be updated in native thread via UIManagerModule

Change NATIVE_PROPS_WHITELIST to UI_THREAD_PROPS_WHITELIST and also change comment to tell that the props are updated directly on UI thread

Change JS_PROPS_HANDLED_ to NATIVE_THREAD_PROPS_WHITELIST

@@ -68,13 +69,15 @@
public double currentFrameTimeMs;
public final UpdateContext updateContext;
public Set<String> nativeProps = Collections.emptySet();
public Set<String> jsPropsHandledNatively = Collections.emptySet();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use uiProps for what used to be nativeProps and nativeProps for jsPropsHandledNatively

new GuardedRunnable(mContext) {
@Override
public void runGuarded() {
mUIManager.onBatchComplete();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we shouldn't just call onBatchComplete like that. This may intercept batched calls being made at the same time from JS. Would be the best to detect if we are in the middle of a batch and if so we can skip calling onBatchComplete and rely on getting it dispatched from JS thread. Also May be worth enqueuing all the UIManager operations here such that we can call it from a single runnable without risking some other operations being enqueued in the meantime

@Override
public void runGuarded() {
while (!mOperationsInBatch.isEmpty()) {
NativeUpdateOperation op = mOperationsInBatch.remove();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sync this quuee

@@ -284,6 +318,10 @@ public void disconnectNodeFromView(int nodeID, int viewTag) {
((PropsNode) node).disconnectFromView(viewTag);
}

public void setUpdateView(int viewTag, WritableMap nativeProps) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename

@@ -137,6 +155,30 @@ private void onAnimationFrame(long frameTimeNanos) {
Node.runUpdates(updateContext);
}

if (!mOperationsInBatch.isEmpty()) {
final Queue<NativeUpdateOperation> copiedProps = new LinkedList<>(mOperationsInBatch);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename copiedProps

evt.putMap("props", jsProps);
mNodesManager.sendEvent("onReanimatedPropsChange", evt);
if (hasNativeProps) {
mNodesManager.updateView(mConnectedViewTag, nativeProps);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enqueueUpdateViewOnNativeThread

@@ -0,0 +1,8 @@
package com.facebook.react.uimanager;

// This class has been made in order to export package method of UIImplementation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use javadoc format to document this class

ios/REAModule.m Outdated
@@ -107,13 +107,15 @@ - (void)setBridge:(RCTBridge *)bridge
}];
}

RCT_EXPORT_METHOD(configureNativeProps:(nonnull NSArray<NSString *> *)nativeProps)
RCT_EXPORT_METHOD(configureProps:(nonnull NSArray<NSString *> *)nativeProps
nativeProps:(nonnull NSArray<NSString *> *)uiProps)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uiProps:(nonnull NSArray<NSString *> *)uiProps)

boolean hasNativeProps = false;
boolean hasJSProps = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets keep the code responsible for updating props in JS. I believe there are still some props that we haven't whitelisted, we don't want to restrict usages that are curerntly possible

RCTExecuteOnUIManagerQueue(^{
BOOL shouldFinishBatch = ((NSHashTable<RCTShadowView *> *)[self.uiManager valueForKey:@"_shadowViewsWithUpdatedChildren"]).count == 0;
for (int i = 0; i < copiedNumberOfOperationsInBatch; i++) {
[self.uiManager updateView:copiedProps[i].reactTag viewName:copiedProps[i].viewName props:copiedProps[i].nativeProps];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copiedProps[i](self.uiManager);

- (void)updateView:(nonnull NSNumber *)reactTag
viewName:(NSString *) viewName
nativeProps:(NSMutableDictionary *)nativeProps {
[_operationsInBatch addObject:[[REANativeUpdateOperation alloc] initWithReactTag:reactTag viewName:viewName nativeProps:nativeProps]];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[_operationsInBatch addObject:^(RCTUIManager *uiManager) {
  [uiManager updateView:reactTag viewName:viewName props:nativeProps];
}

[self.uiManager updateView:copiedProps[i].reactTag viewName:copiedProps[i].viewName props:copiedProps[i].nativeProps];
}
if (shouldFinishBatch) {
[self.uiManager batchDidComplete];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -137,6 +155,30 @@ private void onAnimationFrame(long frameTimeNanos) {
Node.runUpdates(updateContext);
}

if (!mOperationsInBatch.isEmpty()) {
final Queue<NativeUpdateOperation> copiedOperationsQueue = new LinkedList<>(mOperationsInBatch);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final Queue<NativeUpdateOperation> copiedOperationsQueue = mOperationsInBatch;
mOpertionsInBatch = new LinkedList<>();

}
}
if (shouldDispatchUpdates) {
mUIImplementation.dispatchViewUpdates(-1); // no associated batchId
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kmagiera,
decided not to use onBatchCompleted because it sometimes makes unexpected behaviour.
While changing screen via navigator it sometimes "blink" with old layout (v easy to repro)
Indeed I figured out that batchId should not have any impact because it only matters in systrace.
https://github.com/facebook/react-native/search?q=batchId&unscoped_q=batchId&type=Code
But it makes this error 🤷‍♂️

#import "Nodes/REAAlwaysNode.h"

@interface RCTUIManager ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comment

@osdnk osdnk merged commit d54f70e into master Aug 14, 2018
@osdnk osdnk deleted the update-jsprops-without-bridge branch December 19, 2019 16:31
@hannojg hannojg mentioned this pull request Aug 2, 2021
3 tasks
piaskowyk pushed a commit that referenced this pull request Jun 12, 2023
This commit
facebook/react-native@2558c3d
added string to `transform` type and it broke Reanimated types.

<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

fixes
[#45](#4548)
LevkovEgor pushed a commit to jobtoday/react-native-reanimated that referenced this pull request Jul 5, 2023
This commit
facebook/react-native@2558c3d
added string to `transform` type and it broke Reanimated types.

<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

fixes
[software-mansion#45](software-mansion#4548)
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants