Skip to content

Commit faead14

Browse files
authored
Infra/refactor view - convert to function component and use modifiers and themeProps hooks (#2146)
* Add new infra for modifiers and themeProps hooks * Convert view to function component and use modifiers and theme props hooks * Create global ThemeComponent interface * Remove redundant ThemeComponent type in asBaseComponent * memoize view style
1 parent 86fd7fd commit faead14

File tree

5 files changed

+91
-105
lines changed

5 files changed

+91
-105
lines changed

src/commons/asBaseComponent.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ export interface AsBaseComponentOptions {
1818
modifiersOptions?: Modifiers.ModifiersOptions;
1919
}
2020

21-
// TODO: find a proper way to inject this type in the private repo
22-
type ThemeComponent = {
23-
useCustomTheme?: boolean;
24-
};
25-
2621
const EMPTY_MODIFIERS = {};
2722

2823
function asBaseComponent<PROPS, STATICS = {}>(WrappedComponent: React.ComponentType<any>,

src/components/chipsInput/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ class ChipsInput extends Component<OwnProps, State> {
484484
const Container = maxHeight ? ScrollView : View;
485485
return (
486486
<Container
487+
// @ts-expect-error
487488
ref={this.scrollRef}
488489
showsVerticalScrollIndicator={false}
489490
style={!maxHeight && styles.tagsList}

src/components/toast/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import Button from '../button';
1111
import Text from '../text';
1212

1313

14-
// Create animated view base on uilib view for the safeArea support
15-
const AnimatedView = Animated.createAnimatedComponent(View);
1614
const COLOR = Colors.white;
1715

1816
/**
@@ -330,22 +328,24 @@ export default class Toast extends PureBaseComponent {
330328
});
331329

332330
return (
333-
<AnimatedView
331+
<View
332+
animated
334333
testID={testID}
335334
style={[positionStyle, {zIndex, transform: [{translateY}]}]}
336335
pointerEvents={'box-none'}
337336
>
338337
{!isTop && !!toastHeight && this.renderAttachmentContent()}
339-
<AnimatedView
338+
<View
340339
useSafeArea
340+
animated
341341
style={[{backgroundColor: bg, opacity}, style]}
342342
onLayout={this.onToastLayout}
343343
pointerEvents={visible ? 'auto' : 'none'}
344344
>
345345
{this.renderContent()}
346-
</AnimatedView>
346+
</View>
347347
{isTop && !!toastHeight && this.renderAttachmentContent()}
348-
</AnimatedView>
348+
</View>
349349
);
350350
}
351351
}

src/components/view/index.tsx

Lines changed: 80 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1-
import React, {PureComponent} from 'react';
1+
import {useModifiers, useThemeProps} from 'hooks';
2+
import React, {useEffect, useMemo, useState} from 'react';
23
import {View as RNView, SafeAreaView, Animated, ViewProps as RNViewProps, StyleProp, ViewStyle} from 'react-native';
34
import Reanimated from 'react-native-reanimated';
4-
import {
5-
Constants,
6-
asBaseComponent,
7-
forwardRef,
8-
BaseComponentInjectedProps,
9-
ForwardRefInjectedProps,
10-
ContainerModifiers
11-
} from '../../commons/new';
5+
import {Constants, ContainerModifiers} from '../../commons/new';
126

13-
export interface ViewProps extends Omit<RNViewProps, 'style'>, ContainerModifiers {
7+
export interface ViewProps extends Omit<RNViewProps, 'style'>, ThemeComponent, ContainerModifiers {
148
/**
159
* If true, will render as SafeAreaView
1610
*/
@@ -46,106 +40,98 @@ export interface ViewProps extends Omit<RNViewProps, 'style'>, ContainerModifier
4640
style?: StyleProp<ViewStyle | Animated.AnimatedProps<ViewStyle>>;
4741
}
4842

49-
type PropsTypes = BaseComponentInjectedProps & ForwardRefInjectedProps & ViewProps;
50-
51-
interface ViewState {
52-
ready: boolean;
53-
}
43+
const modifiersOptions = {
44+
backgroundColor: true,
45+
borderRadius: true,
46+
paddings: true,
47+
margins: true,
48+
alignments: true,
49+
flex: true,
50+
position: true
51+
};
5452

5553
/**
5654
* @description: An enhanced View component
5755
* @extends: View
5856
* @extendsLink: https://reactnative.dev/docs/view
5957
* @modifiers: margins, paddings, alignments, background, borderRadius
6058
*/
61-
class View extends PureComponent<PropsTypes, ViewState> {
62-
static displayName = 'View';
63-
private Container: React.ClassType<any, any, any>;
64-
65-
constructor(props: PropsTypes) {
66-
super(props);
67-
68-
this.Container = props.useSafeArea && Constants.isIOS ? SafeAreaView : RNView;
69-
if (props.reanimated) {
70-
this.Container = Reanimated.createAnimatedComponent(this.Container);
71-
} else if (props.animated) {
72-
this.Container = Animated.createAnimatedComponent(this.Container);
73-
}
74-
75-
this.state = {
76-
ready: !props.renderDelay
77-
};
78-
}
59+
function View(props: ViewProps, ref: any) {
60+
const themeProps = useThemeProps(props, 'View');
61+
const {
62+
renderDelay,
63+
style,
64+
// (!) extract left, top, bottom... props to avoid passing them on Android
65+
/* eslint-disable */
66+
left,
67+
top,
68+
right,
69+
bottom,
70+
flex: propsFlex,
71+
/* eslint-enable */
72+
inaccessible,
73+
useSafeArea,
74+
animated,
75+
reanimated,
76+
children,
77+
...others
78+
} = themeProps;
79+
const {backgroundColor, borderRadius, paddings, margins, alignments, flexStyle, positionStyle} = useModifiers(themeProps,
80+
modifiersOptions);
81+
const [ready, setReady] = useState(!renderDelay);
7982

80-
componentDidMount() {
81-
const {renderDelay} = this.props;
83+
useEffect(() => {
8284
if (renderDelay) {
8385
setTimeout(() => {
84-
this.setState({ready: true});
86+
setReady(true);
8587
}, renderDelay);
8688
}
87-
}
89+
}, []);
8890

89-
// TODO: do we need this?
90-
setNativeProps(nativeProps: any) {
91-
//@ts-ignore
92-
this._root.setNativeProps(nativeProps); // eslint-disable-line
93-
}
91+
const ViewContainer = useMemo(() => {
92+
const container = useSafeArea && Constants.isIOS ? SafeAreaView : RNView;
9493

95-
render() {
96-
if (!this.state.ready) {
97-
return null;
94+
if (reanimated) {
95+
return Reanimated.createAnimatedComponent(container);
96+
} else if (animated) {
97+
return Animated.createAnimatedComponent(container);
9898
}
9999

100-
// (!) extract left, top, bottom... props to avoid passing them on Android
101-
// eslint-disable-next-line
102-
const {
103-
modifiers,
104-
style,
105-
/* eslint-disable */
106-
left,
107-
top,
108-
right,
109-
bottom,
110-
flex: propsFlex,
111-
/* eslint-enable */
112-
forwardedRef,
113-
inaccessible,
114-
...others
115-
} = this.props;
116-
const {backgroundColor, borderRadius, paddings, margins, alignments, flexStyle, positionStyle} = modifiers;
117-
const Element = this.Container;
118-
return (
119-
<Element
120-
accessibilityElementsHidden={inaccessible}
121-
importantForAccessibility={inaccessible ? 'no-hide-descendants' : undefined}
122-
{...others}
123-
style={[
124-
backgroundColor && {backgroundColor},
125-
borderRadius && {borderRadius},
126-
flexStyle,
127-
positionStyle,
128-
paddings,
129-
margins,
130-
alignments,
131-
style
132-
]}
133-
ref={forwardedRef}
134-
>
135-
{this.props.children}
136-
</Element>
137-
);
100+
return container;
101+
}, [useSafeArea, animated, reanimated]);
102+
103+
const _style = useMemo(() => {
104+
return [
105+
backgroundColor && {
106+
backgroundColor
107+
},
108+
borderRadius && {
109+
borderRadius
110+
},
111+
flexStyle,
112+
positionStyle,
113+
paddings,
114+
margins,
115+
alignments,
116+
style
117+
];
118+
}, [backgroundColor, borderRadius, flexStyle, positionStyle, paddings, margins, alignments, style]);
119+
120+
if (!ready) {
121+
return null;
138122
}
139-
}
140123

141-
const modifiersOptions = {
142-
backgroundColor: true,
143-
borderRadius: true,
144-
paddings: true,
145-
margins: true,
146-
alignments: true,
147-
flex: true,
148-
position: true
149-
};
124+
return (
125+
<ViewContainer
126+
accessibilityElementsHidden={inaccessible}
127+
importantForAccessibility={inaccessible ? 'no-hide-descendants' : undefined}
128+
{...others}
129+
style={_style}
130+
ref={ref}
131+
>
132+
{children}
133+
</ViewContainer>
134+
);
135+
}
150136

151-
export default asBaseComponent<ViewProps>(forwardRef(View), {modifiersOptions});
137+
export default React.forwardRef<RNView, ViewProps>(View);

typings/globalTypes.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ declare module 'react-native-measureme';
1414
interface Extendable {
1515
[key: string]: any;
1616
}
17+
18+
interface ThemeComponent {
19+
useCustomTheme?: boolean;
20+
}

0 commit comments

Comments
 (0)