UNPKG

4.52 kBPlain TextView Raw
1'use strict';
2import { NativeEventEmitter, Platform, findNodeHandle } from 'react-native';
3import type { NativeModule } from 'react-native';
4import { shouldBeUseWeb } from '../reanimated2/PlatformChecker';
5import type { StyleProps } from '../reanimated2';
6import { runOnJS, runOnUIImmediately } from '../reanimated2/threads';
7import type {
8 AnimatedComponentProps,
9 IAnimatedComponentInternal,
10 IJSPropsUpdater,
11 InitialComponentProps,
12} from './commonTypes';
13import NativeReanimatedModule from '../specs/NativeReanimatedModule';
14
15interface ListenerData {
16 viewTag: number;
17 props: StyleProps;
18}
19
20const SHOULD_BE_USE_WEB = shouldBeUseWeb();
21
22class JSPropsUpdaterPaper implements IJSPropsUpdater {
23 private static _tagToComponentMapping = new Map();
24 private _reanimatedEventEmitter: NativeEventEmitter;
25
26 constructor() {
27 this._reanimatedEventEmitter = new NativeEventEmitter(
28 // NativeEventEmitter only uses this parameter on iOS.
29 Platform.OS === 'ios'
30 ? (NativeReanimatedModule as unknown as NativeModule)
31 : undefined
32 );
33 }
34
35 public addOnJSPropsChangeListener(
36 animatedComponent: React.Component<
37 AnimatedComponentProps<InitialComponentProps>
38 > &
39 IAnimatedComponentInternal
40 ) {
41 const viewTag = findNodeHandle(animatedComponent);
42 JSPropsUpdaterPaper._tagToComponentMapping.set(viewTag, animatedComponent);
43 if (JSPropsUpdaterPaper._tagToComponentMapping.size === 1) {
44 const listener = (data: ListenerData) => {
45 const component = JSPropsUpdaterPaper._tagToComponentMapping.get(
46 data.viewTag
47 );
48 component?._updateFromNative(data.props);
49 };
50 this._reanimatedEventEmitter.addListener(
51 'onReanimatedPropsChange',
52 listener
53 );
54 }
55 }
56
57 public removeOnJSPropsChangeListener(
58 animatedComponent: React.Component<
59 AnimatedComponentProps<InitialComponentProps>
60 > &
61 IAnimatedComponentInternal
62 ) {
63 const viewTag = findNodeHandle(animatedComponent);
64 JSPropsUpdaterPaper._tagToComponentMapping.delete(viewTag);
65 if (JSPropsUpdaterPaper._tagToComponentMapping.size === 0) {
66 this._reanimatedEventEmitter.removeAllListeners(
67 'onReanimatedPropsChange'
68 );
69 }
70 }
71}
72
73class JSPropsUpdaterFabric implements IJSPropsUpdater {
74 private static _tagToComponentMapping = new Map();
75 private static isInitialized = false;
76
77 constructor() {
78 if (!JSPropsUpdaterFabric.isInitialized) {
79 const updater = (viewTag: number, props: unknown) => {
80 const component =
81 JSPropsUpdaterFabric._tagToComponentMapping.get(viewTag);
82 component?._updateFromNative(props);
83 };
84 runOnUIImmediately(() => {
85 'worklet';
86 global.updateJSProps = (viewTag: number, props: unknown) => {
87 runOnJS(updater)(viewTag, props);
88 };
89 })();
90 JSPropsUpdaterFabric.isInitialized = true;
91 }
92 }
93
94 public addOnJSPropsChangeListener(
95 animatedComponent: React.Component<
96 AnimatedComponentProps<InitialComponentProps>
97 > &
98 IAnimatedComponentInternal
99 ) {
100 if (!JSPropsUpdaterFabric.isInitialized) {
101 return;
102 }
103 const viewTag = findNodeHandle(animatedComponent);
104 JSPropsUpdaterFabric._tagToComponentMapping.set(viewTag, animatedComponent);
105 }
106
107 public removeOnJSPropsChangeListener(
108 animatedComponent: React.Component<
109 AnimatedComponentProps<InitialComponentProps>
110 > &
111 IAnimatedComponentInternal
112 ) {
113 if (!JSPropsUpdaterFabric.isInitialized) {
114 return;
115 }
116 const viewTag = findNodeHandle(animatedComponent);
117 JSPropsUpdaterFabric._tagToComponentMapping.delete(viewTag);
118 }
119}
120
121class JSPropsUpdaterWeb implements IJSPropsUpdater {
122 public addOnJSPropsChangeListener(
123 _animatedComponent: React.Component<
124 AnimatedComponentProps<InitialComponentProps>
125 > &
126 IAnimatedComponentInternal
127 ) {
128 // noop
129 }
130
131 public removeOnJSPropsChangeListener(
132 _animatedComponent: React.Component<
133 AnimatedComponentProps<InitialComponentProps>
134 > &
135 IAnimatedComponentInternal
136 ) {
137 // noop
138 }
139}
140
141type JSPropsUpdaterOptions =
142 | typeof JSPropsUpdaterWeb
143 | typeof JSPropsUpdaterFabric
144 | typeof JSPropsUpdaterPaper;
145
146let JSPropsUpdater: JSPropsUpdaterOptions;
147if (SHOULD_BE_USE_WEB) {
148 JSPropsUpdater = JSPropsUpdaterWeb;
149} else if (global._IS_FABRIC) {
150 JSPropsUpdater = JSPropsUpdaterFabric;
151} else {
152 JSPropsUpdater = JSPropsUpdaterPaper;
153}
154
155export default JSPropsUpdater;