Skip to content

Commit b1e3428

Browse files
committed
feat: [:art:] change to functional component
1 parent 63fd4c4 commit b1e3428

File tree

3 files changed

+123
-131
lines changed

3 files changed

+123
-131
lines changed

src/component/Dot.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* Created by rouge on 11/09/2019.
44
* Converted to Typescript on 14/07/2020.
5-
*
5+
* Converted to Functional component. on 21/09/2021
66
*/
77
import React, { useEffect, useState } from 'react';
88
import { Animated } from 'react-native';

src/component/EmptyDot.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
2-
*
32
* Created by rouge on 11/09/2019.
3+
* Converted to Functional component. on 21/09/2021
44
*/
55
import React from 'react';
66
import { StyleSheet, View } from 'react-native';

src/index.tsx

Lines changed: 121 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
*
33
* Created by rouge on 11/09/2019.
44
* Converted to Typescript on 14/07/2020.
5-
*
5+
* Converted to Functional component. on 21/09/2021
66
*/
7-
import React from 'react';
7+
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
88
import { ScrollView, View, ViewStyle, StyleProp } from 'react-native';
99
import Dot from './component/Dot';
1010
import EmptyDot, { defaultEmptyDotSize } from './component/EmptyDot';
11+
import { usePrevious } from 'react-use';
1112

1213
export interface IDotContainerProps {
1314
curPage: number;
@@ -19,141 +20,50 @@ export interface IDotContainerProps {
1920

2021
const ONE_EMPTY_DOT_SIZE = defaultEmptyDotSize * defaultEmptyDotSize;
2122

22-
class DotContainer extends React.Component<IDotContainerProps> {
23-
private refScrollView: ScrollView | null = null;
23+
const DotContainer: React.FC<IDotContainerProps> = (props) => {
24+
const refScrollView = useRef<ScrollView>(null);
25+
const prevPage = usePrevious(props.curPage);
2426

25-
shouldComponentUpdate(nextProps: IDotContainerProps) {
26-
if (this.props.curPage === nextProps.curPage) {
27-
// prevent unnecessary re-render caused by external change
28-
return false;
29-
}
27+
const getSizeRatio = useCallback<() => number>(() => {
28+
if (!props.sizeRatio) return 1.0;
3029

31-
return true;
32-
}
30+
return Math.max(1.0, props.sizeRatio);
31+
}, [props.sizeRatio]);
3332

34-
componentDidUpdate(prevProps: IDotContainerProps) {
35-
if (this.props.maxPage > 4 && prevProps.curPage !== this.props.curPage)
36-
this.scrollTo(this.props.curPage);
37-
}
33+
const scrollTo = useCallback<(index: number, animated?: boolean) => void>(
34+
(index, animated = true) => {
35+
if (!refScrollView) return;
3836

39-
render() {
40-
const { curPage, maxPage, activeDotColor } = this.props;
41-
const list = [...Array(maxPage).keys()];
42-
43-
let normalizedPage = curPage;
44-
if (curPage < 0) {
45-
normalizedPage = 0;
46-
}
47-
48-
if (curPage > maxPage - 1) {
49-
normalizedPage = maxPage - 1;
50-
}
51-
const sizeRatio = this.getSizeRatio();
52-
53-
const container = this.getContainerStyle();
54-
55-
if (maxPage < 5) {
56-
return (
57-
<View style={container}>
58-
{list.map((i) => {
59-
return (
60-
<Dot
61-
key={i}
62-
idx={i}
63-
sizeRatio={sizeRatio}
64-
curPage={normalizedPage}
65-
maxPage={maxPage}
66-
activeColor={activeDotColor}
67-
/>
68-
);
69-
})}
70-
</View>
71-
);
72-
}
37+
const sizeRatio = getSizeRatio();
38+
const FIRST_EMPTY_DOT_SPACE = ONE_EMPTY_DOT_SIZE * 2;
39+
const MOVE_DISTANCE = ONE_EMPTY_DOT_SIZE * sizeRatio;
7340

74-
return (
75-
<View
76-
style={container}
77-
onLayout={() => {
78-
// scroll to right index on initial render
79-
this.scrollTo(this.props.curPage, false);
80-
}}
81-
>
82-
<ScrollView
83-
ref={(ref) => {
84-
this.refScrollView = ref;
85-
}}
86-
contentContainerStyle={{
87-
alignItems: 'center',
88-
}}
89-
bounces={false}
90-
horizontal={!this.props.vertical}
91-
scrollEnabled={false}
92-
showsVerticalScrollIndicator={false}
93-
showsHorizontalScrollIndicator={false}
94-
>
95-
{/* previous empty dummy dot */}
96-
<EmptyDot sizeRatio={sizeRatio} />
97-
<EmptyDot sizeRatio={sizeRatio} />
98-
99-
{list.map((i) => {
100-
return (
101-
<Dot
102-
sizeRatio={sizeRatio}
103-
key={i}
104-
idx={i}
105-
curPage={normalizedPage}
106-
maxPage={maxPage}
107-
activeColor={activeDotColor}
108-
/>
109-
);
110-
})}
111-
112-
{/* previous empty dummy dot */}
113-
<EmptyDot sizeRatio={sizeRatio} />
114-
<EmptyDot sizeRatio={sizeRatio} />
115-
</ScrollView>
116-
</View>
117-
);
118-
}
119-
120-
scrollTo(index: number, animated = true) {
121-
if (!this.refScrollView) return;
122-
123-
const sizeRatio = this.getSizeRatio();
124-
const FIRST_EMPTY_DOT_SPACE = ONE_EMPTY_DOT_SIZE * 2;
125-
const MOVE_DISTANCE = ONE_EMPTY_DOT_SIZE * sizeRatio;
126-
127-
const moveTo = Math.max(
128-
0,
129-
FIRST_EMPTY_DOT_SPACE + (index - 4) * MOVE_DISTANCE
130-
);
41+
const moveTo = Math.max(
42+
0,
43+
FIRST_EMPTY_DOT_SPACE + (index - 4) * MOVE_DISTANCE
44+
);
13145

132-
if (this.props.vertical) {
133-
this.refScrollView.scrollTo({
134-
x: 0,
135-
y: moveTo,
46+
if (props.vertical) {
47+
refScrollView.current?.scrollTo({
48+
x: 0,
49+
y: moveTo,
50+
animated,
51+
});
52+
return;
53+
}
54+
55+
refScrollView.current?.scrollTo({
56+
x: moveTo,
57+
y: 0,
13658
animated,
13759
});
138-
return;
139-
}
140-
141-
this.refScrollView.scrollTo({
142-
x: moveTo,
143-
y: 0,
144-
animated,
145-
});
146-
}
147-
148-
getSizeRatio(): number {
149-
if (!this.props.sizeRatio) return 1.0;
60+
},
61+
[getSizeRatio, props.vertical]
62+
);
15063

151-
return Math.max(1.0, this.props.sizeRatio);
152-
}
153-
154-
getContainerStyle(): StyleProp<ViewStyle> {
155-
const { vertical } = this.props;
156-
const sizeRatio = this.getSizeRatio();
64+
const getContainerStyle = useCallback<() => StyleProp<ViewStyle>>(() => {
65+
const { vertical } = props;
66+
const sizeRatio = getSizeRatio();
15767
const containerSize = 84 * sizeRatio;
15868

15969
return {
@@ -162,7 +72,89 @@ class DotContainer extends React.Component<IDotContainerProps> {
16272
maxHeight: vertical ? containerSize : undefined,
16373
maxWidth: vertical ? undefined : containerSize,
16474
};
75+
}, [getSizeRatio, props]);
76+
77+
useEffect(() => {
78+
if (props.maxPage > 4 && prevPage !== props.curPage)
79+
scrollTo(props.curPage);
80+
}, [prevPage, props.curPage, props.maxPage, scrollTo]);
81+
82+
const { curPage, maxPage, activeDotColor } = props;
83+
const list = useMemo(() => [...Array(maxPage).keys()], [maxPage]);
84+
85+
let normalizedPage = curPage;
86+
if (curPage < 0) {
87+
normalizedPage = 0;
16588
}
166-
}
89+
90+
if (curPage > maxPage - 1) {
91+
normalizedPage = maxPage - 1;
92+
}
93+
const sizeRatio = getSizeRatio();
94+
95+
const container = getContainerStyle();
96+
97+
if (maxPage < 5) {
98+
return (
99+
<View style={container}>
100+
{list.map((i) => {
101+
return (
102+
<Dot
103+
key={i}
104+
idx={i}
105+
sizeRatio={sizeRatio}
106+
curPage={normalizedPage}
107+
maxPage={maxPage}
108+
activeColor={activeDotColor}
109+
/>
110+
);
111+
})}
112+
</View>
113+
);
114+
}
115+
116+
return (
117+
<View
118+
style={container}
119+
onLayout={() => {
120+
// scroll to right index on initial render
121+
scrollTo(props.curPage, false);
122+
}}
123+
>
124+
<ScrollView
125+
ref={refScrollView}
126+
contentContainerStyle={{
127+
alignItems: 'center',
128+
}}
129+
bounces={false}
130+
horizontal={!props.vertical}
131+
scrollEnabled={false}
132+
showsVerticalScrollIndicator={false}
133+
showsHorizontalScrollIndicator={false}
134+
>
135+
{/* previous empty dummy dot */}
136+
<EmptyDot sizeRatio={sizeRatio} />
137+
<EmptyDot sizeRatio={sizeRatio} />
138+
139+
{list.map((i) => {
140+
return (
141+
<Dot
142+
sizeRatio={sizeRatio}
143+
key={i}
144+
idx={i}
145+
curPage={normalizedPage}
146+
maxPage={maxPage}
147+
activeColor={activeDotColor}
148+
/>
149+
);
150+
})}
151+
152+
{/* previous empty dummy dot */}
153+
<EmptyDot sizeRatio={sizeRatio} />
154+
<EmptyDot sizeRatio={sizeRatio} />
155+
</ScrollView>
156+
</View>
157+
);
158+
};
167159

168160
export default DotContainer;

0 commit comments

Comments
 (0)