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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve code quality of helper classes of createAnimatedComponent #5804

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/createAnimatedComponent/InlinePropManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';
import type { StyleProps } from '../reanimated2';
import type {
IAnimatedComponentInternal,
AnimatedComponent,
AnimatedComponentProps,
IInlinePropManager,
ViewInfo,
Expand Down Expand Up @@ -132,14 +132,15 @@ export class InlinePropManager implements IInlinePropManager {
_inlinePropsViewDescriptors: ViewDescriptorsSet | null = null;
_inlinePropsMapperId: number | null = null;
_inlineProps: StyleProps = {};
Comment on lines 132 to 134
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
_inlinePropsViewDescriptors: ViewDescriptorsSet | null = null;
_inlinePropsMapperId: number | null = null;
_inlineProps: StyleProps = {};
private _inlinePropsViewDescriptors: ViewDescriptorsSet | null = null;
private _inlinePropsMapperId: number | null = null;
private _inlineProps: StyleProps = {};

private _component: AnimatedComponent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this is called _component and in JSPropUpdater we call it _animatedComponent? Both are animated, aren't they?


public attachInlineProps(
animatedComponent: React.Component<unknown, unknown> &
IAnimatedComponentInternal,
viewInfo: ViewInfo
) {
constructor(component: AnimatedComponent) {
this._component = component;
}

public attachInlineProps(viewInfo: ViewInfo) {
const newInlineProps: Record<string, unknown> =
extractSharedValuesMapFromProps(animatedComponent.props);
extractSharedValuesMapFromProps(this._component.props);
const hasChanged = inlinePropsHasChanged(newInlineProps, this._inlineProps);

if (hasChanged) {
Expand All @@ -162,7 +163,7 @@ export class InlinePropManager implements IInlinePropManager {
this._inlinePropsViewDescriptors.shareableViewDescriptors;

const maybeViewRef = SHOULD_BE_USE_WEB
? ({ items: new Set([animatedComponent]) } as ViewRefSet<unknown>) // see makeViewsRefSet
? ({ items: new Set([this._component]) } as ViewRefSet<unknown>) // see makeViewsRefSet
: undefined;
const updaterFunction = () => {
'worklet';
Expand Down
76 changes: 24 additions & 52 deletions src/createAnimatedComponent/JSPropsUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ import type { NativeModule } from 'react-native';
import { shouldBeUseWeb } from '../reanimated2/PlatformChecker';
import type { StyleProps } from '../reanimated2';
import { runOnJS, runOnUIImmediately } from '../reanimated2/threads';
import type {
AnimatedComponentProps,
IAnimatedComponentInternal,
IJSPropsUpdater,
InitialComponentProps,
} from './commonTypes';
import type { AnimatedComponent, IJSPropsUpdater } from './commonTypes';
import NativeReanimatedModule from '../specs/NativeReanimatedModule';

interface ListenerData {
Expand All @@ -22,24 +17,24 @@ const SHOULD_BE_USE_WEB = shouldBeUseWeb();
class JSPropsUpdaterPaper implements IJSPropsUpdater {
private static _tagToComponentMapping = new Map();
private _reanimatedEventEmitter: NativeEventEmitter;
private _animatedComponent: AnimatedComponent;

constructor() {
constructor(animatedComponent: AnimatedComponent) {
this._reanimatedEventEmitter = new NativeEventEmitter(
// NativeEventEmitter only uses this parameter on iOS.
Platform.OS === 'ios'
? (NativeReanimatedModule as unknown as NativeModule)
: undefined
);
this._animatedComponent = animatedComponent;
}

public addOnJSPropsChangeListener(
animatedComponent: React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal
) {
const viewTag = findNodeHandle(animatedComponent);
JSPropsUpdaterPaper._tagToComponentMapping.set(viewTag, animatedComponent);
public addOnJSPropsChangeListener() {
const viewTag = findNodeHandle(this._animatedComponent);
JSPropsUpdaterPaper._tagToComponentMapping.set(
viewTag,
this._animatedComponent
);
if (JSPropsUpdaterPaper._tagToComponentMapping.size === 1) {
const listener = (data: ListenerData) => {
const component = JSPropsUpdaterPaper._tagToComponentMapping.get(
Expand All @@ -54,13 +49,8 @@ class JSPropsUpdaterPaper implements IJSPropsUpdater {
}
}

public removeOnJSPropsChangeListener(
animatedComponent: React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal
) {
const viewTag = findNodeHandle(animatedComponent);
public removeOnJSPropsChangeListener() {
const viewTag = findNodeHandle(this._animatedComponent);
JSPropsUpdaterPaper._tagToComponentMapping.delete(viewTag);
if (JSPropsUpdaterPaper._tagToComponentMapping.size === 0) {
this._reanimatedEventEmitter.removeAllListeners(
Expand All @@ -73,13 +63,14 @@ class JSPropsUpdaterPaper implements IJSPropsUpdater {
class JSPropsUpdaterFabric implements IJSPropsUpdater {
private static _tagToComponentMapping = new Map();
private static isInitialized = false;
private _component: AnimatedComponent;

constructor() {
constructor(component: AnimatedComponent) {
if (!JSPropsUpdaterFabric.isInitialized) {
const updater = (viewTag: number, props: unknown) => {
const component =
const componentToUpdate =
JSPropsUpdaterFabric._tagToComponentMapping.get(viewTag);
component?._updateFromNative(props);
componentToUpdate?._updateFromNative(props);
};
runOnUIImmediately(() => {
'worklet';
Expand All @@ -89,51 +80,32 @@ class JSPropsUpdaterFabric implements IJSPropsUpdater {
})();
JSPropsUpdaterFabric.isInitialized = true;
}
this._component = component;
}

public addOnJSPropsChangeListener(
animatedComponent: React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal
) {
public addOnJSPropsChangeListener() {
if (!JSPropsUpdaterFabric.isInitialized) {
return;
}
const viewTag = findNodeHandle(animatedComponent);
JSPropsUpdaterFabric._tagToComponentMapping.set(viewTag, animatedComponent);
const viewTag = findNodeHandle(this._component);
JSPropsUpdaterFabric._tagToComponentMapping.set(viewTag, this._component);
}

public removeOnJSPropsChangeListener(
animatedComponent: React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal
) {
public removeOnJSPropsChangeListener() {
if (!JSPropsUpdaterFabric.isInitialized) {
return;
}
const viewTag = findNodeHandle(animatedComponent);
const viewTag = findNodeHandle(this._component);
JSPropsUpdaterFabric._tagToComponentMapping.delete(viewTag);
}
}

class JSPropsUpdaterWeb implements IJSPropsUpdater {
public addOnJSPropsChangeListener(
_animatedComponent: React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal
) {
public addOnJSPropsChangeListener() {
// noop
}

public removeOnJSPropsChangeListener(
_animatedComponent: React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal
) {
public removeOnJSPropsChangeListener() {
// noop
}
}
Expand Down
22 changes: 4 additions & 18 deletions src/createAnimatedComponent/JSPropsUpdater.web.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,12 @@
'use strict';
import type {
AnimatedComponentProps,
IAnimatedComponentInternal,
InitialComponentProps,
} from './commonTypes';
import type { IJSPropsUpdater } from './commonTypes';

export default class JSPropsUpdaterWeb {
public addOnJSPropsChangeListener(
_animatedComponent: React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal
) {
export default class JSPropsUpdaterWeb implements IJSPropsUpdater {
public addOnJSPropsChangeListener() {
// noop
}

public removeOnJSPropsChangeListener(
_animatedComponent: React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal
) {
public removeOnJSPropsChangeListener() {
// noop
}
}
25 changes: 14 additions & 11 deletions src/createAnimatedComponent/PropsFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import type {
AnimatedComponentProps,
AnimatedProps,
InitialComponentProps,
IAnimatedComponentInternal,
IPropsFilter,
AnimatedComponent,
} from './commonTypes';
import { flattenArray, has } from './utils';
import { StyleSheet } from 'react-native';
Expand All @@ -22,12 +22,15 @@ function dummyListener() {

export class PropsFilter implements IPropsFilter {
private _initialStyle = {};
private _component: AnimatedComponent;

public filterNonAnimatedProps(
component: React.Component<unknown, unknown> & IAnimatedComponentInternal
): Record<string, unknown> {
const inputProps =
component.props as AnimatedComponentProps<InitialComponentProps>;
constructor(component: AnimatedComponent) {
this._component = component;
}

public filterNonAnimatedProps(): Record<string, unknown> {
const inputProps = this._component
.props as AnimatedComponentProps<InitialComponentProps>;
const props: Record<string, unknown> = {};
for (const key in inputProps) {
const value = inputProps[key];
Expand All @@ -37,8 +40,8 @@ export class PropsFilter implements IPropsFilter {
const processedStyle: StyleProps = styles.map((style) => {
if (style && style.viewDescriptors) {
// this is how we recognize styles returned by useAnimatedStyle
style.viewsRef?.add(component);
if (component._isFirstRender) {
style.viewsRef?.add(this._component);
if (this._component._isFirstRender) {
this._initialStyle = {
...style.initial.value,
...this._initialStyle,
Expand All @@ -47,7 +50,7 @@ export class PropsFilter implements IPropsFilter {
}
return this._initialStyle;
} else if (hasInlineStyles(style)) {
return getInlineStyle(style, component._isFirstRender);
return getInlineStyle(style, this._component._isFirstRender);
} else {
return style;
}
Expand All @@ -61,7 +64,7 @@ export class PropsFilter implements IPropsFilter {
Object.keys(animatedProp.initial.value).forEach((initialValueKey) => {
props[initialValueKey] =
animatedProp.initial?.value[initialValueKey];
animatedProp.viewsRef?.add(component);
animatedProp.viewsRef?.add(this._component);
});
}
} else if (
Expand All @@ -80,7 +83,7 @@ export class PropsFilter implements IPropsFilter {
props[key] = dummyListener;
}
} else if (isSharedValue(value)) {
if (component._isFirstRender) {
if (this._component._isFirstRender) {
props[key] = value.value;
}
} else if (key !== 'onGestureHandlerStateChange' || !isChromeDebugger()) {
Expand Down
26 changes: 10 additions & 16 deletions src/createAnimatedComponent/commonTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,17 @@ export interface ViewInfo {
}

export interface IInlinePropManager {
attachInlineProps(
animatedComponent: React.Component<unknown, unknown>,
viewInfo: ViewInfo
): void;
attachInlineProps(viewInfo: ViewInfo): void;
detachInlineProps(): void;
}

export interface IPropsFilter {
filterNonAnimatedProps: (
component: React.Component<unknown, unknown> & IAnimatedComponentInternal
) => Record<string, unknown>;
filterNonAnimatedProps: () => Record<string, unknown>;
}

export interface IJSPropsUpdater {
addOnJSPropsChangeListener(
animatedComponent: React.Component<unknown, unknown> &
IAnimatedComponentInternal
): void;
removeOnJSPropsChangeListener(
animatedComponent: React.Component<unknown, unknown> &
IAnimatedComponentInternal
): void;
addOnJSPropsChangeListener(): void;
removeOnJSPropsChangeListener(): void;
}

export type LayoutAnimationStaticContext = {
Expand Down Expand Up @@ -101,13 +90,18 @@ export interface IAnimatedComponentInternal {
jestAnimatedStyle: { value: StyleProps };
_component: AnimatedComponentRef | HTMLElement | null;
_sharedElementTransition: SharedTransition | null;
_jsPropsUpdater: IJSPropsUpdater;
_JSPropsUpdater: IJSPropsUpdater;
_InlinePropManager: IInlinePropManager;
_PropsFilter: IPropsFilter;
_viewInfo?: ViewInfo;
context: React.ContextType<typeof SkipEnteringContext>;
}

export type AnimatedComponent = React.Component<
AnimatedComponentProps<InitialComponentProps>
> &
IAnimatedComponentInternal;

export type NestedArray<T> = T | NestedArray<T>[];

export interface InitialComponentProps extends Record<string, unknown> {
Expand Down