Skip to content

Commit f5974d0

Browse files
committed
feat: [:art:] change dot to functional components
1 parent d4862d7 commit f5974d0

File tree

1 file changed

+86
-87
lines changed

1 file changed

+86
-87
lines changed

src/component/Dot.tsx

Lines changed: 86 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4,107 +4,106 @@
44
* Converted to Typescript on 14/07/2020.
55
*
66
*/
7-
import React from 'react';
7+
import React, { useEffect, useState } from 'react';
88
import { Animated } from 'react-native';
9-
9+
import { usePrevious } from 'react-use';
1010
import EmptyDot from './EmptyDot';
11-
import { IPropsDot, IStateDot } from './types/Dot';
12-
import { getDotStyle } from '../util/DotUtils';
13-
14-
class Dot extends React.Component<IPropsDot, IStateDot> {
15-
constructor(props: IPropsDot) {
16-
super(props);
17-
18-
const type = getDotStyle({
11+
import { getDotStyle, IDotStyle } from '../util/DotUtils';
12+
13+
const Dot: React.FC<{
14+
idx: number;
15+
curPage: number;
16+
maxPage: number;
17+
activeColor: string;
18+
sizeRatio: number;
19+
}> = (props) => {
20+
const [animVal] = useState(new Animated.Value(0));
21+
const [animate, setAnimate] = useState(false);
22+
const [type, setType] = useState(() =>
23+
getDotStyle({
1924
idx: props.idx,
2025
curPage: props.curPage,
2126
maxPage: props.maxPage,
22-
});
23-
24-
this.state = {
25-
animVal: new Animated.Value(0),
26-
animate: false,
27-
prevType: type,
28-
type: type,
29-
};
30-
}
27+
})
28+
);
29+
const prevType = usePrevious<IDotStyle>(type);
3130

32-
static getDerivedStateFromProps(nextProps: IPropsDot, prevState: IStateDot) {
31+
useEffect(() => {
3332
const nextType = getDotStyle({
34-
idx: nextProps.idx,
35-
curPage: nextProps.curPage,
36-
maxPage: nextProps.maxPage,
33+
idx: props.idx,
34+
curPage: props.curPage,
35+
maxPage: props.maxPage,
3736
});
38-
const prevType = prevState.type;
39-
40-
return {
41-
animate:
42-
nextType.size !== prevType.size ||
43-
nextType.opacity !== prevType.opacity,
44-
prevType: prevType,
45-
type: nextType,
46-
};
47-
}
48-
49-
componentDidUpdate() {
50-
if (!this.state.animate) return;
5137

52-
this.state.animVal.setValue(0);
53-
54-
Animated.timing(this.state.animVal, {
38+
const nextAnimate =
39+
nextType.size !== (prevType?.size || 3) ||
40+
nextType.opacity !== (prevType?.opacity || 0.2);
41+
42+
setType(nextType);
43+
setAnimate(nextAnimate);
44+
}, [
45+
prevType?.opacity,
46+
prevType?.size,
47+
props.curPage,
48+
props.idx,
49+
props.maxPage,
50+
]);
51+
52+
useEffect(() => {
53+
if (!animate) return;
54+
55+
animVal.setValue(0);
56+
Animated.timing(animVal, {
5557
toValue: 1,
5658
duration: 300,
5759
useNativeDriver: false,
5860
}).start();
59-
}
60-
61-
render() {
62-
const { idx, curPage, sizeRatio } = this.props;
63-
const { prevType, type } = this.state;
64-
65-
if (curPage < 3) {
66-
if (idx >= 5) return <EmptyDot sizeRatio={sizeRatio} />;
67-
} else if (curPage < 4) {
68-
if (idx > 5) return <EmptyDot sizeRatio={sizeRatio} />;
69-
}
70-
71-
const opacity = this.state.animVal.interpolate({
72-
inputRange: [0, 1],
73-
outputRange: [prevType.opacity, type.opacity],
74-
});
61+
}, [animVal, animate, prevType, type]);
7562

76-
const size = this.state.animVal.interpolate({
77-
inputRange: [0, 1],
78-
outputRange: [prevType.size * sizeRatio, type.size * sizeRatio],
79-
});
80-
81-
const borderRadius = this.state.animVal.interpolate({
82-
inputRange: [0, 1],
83-
outputRange: [
84-
prevType.size * sizeRatio * 0.5,
85-
type.size * sizeRatio * 0.5,
86-
],
87-
});
88-
89-
const { activeColor } = this.props;
90-
91-
return (
92-
<Animated.View
93-
style={[
94-
{
95-
backgroundColor: activeColor,
96-
margin: 3 * sizeRatio,
97-
},
98-
{
99-
width: size,
100-
height: size,
101-
borderRadius: borderRadius,
102-
opacity: opacity,
103-
},
104-
]}
105-
/>
106-
);
63+
if (props.curPage < 3) {
64+
if (props.idx >= 5) return <EmptyDot sizeRatio={props.sizeRatio} />;
65+
} else if (props.curPage < 4) {
66+
if (props.idx > 5) return <EmptyDot sizeRatio={props.sizeRatio} />;
10767
}
108-
}
68+
69+
const opacity = animVal.interpolate({
70+
inputRange: [0, 1],
71+
outputRange: [prevType?.opacity || 0.2, type.opacity],
72+
});
73+
74+
const size = animVal.interpolate({
75+
inputRange: [0, 1],
76+
outputRange: [
77+
(prevType?.size || 3) * props.sizeRatio,
78+
type.size * props.sizeRatio,
79+
],
80+
});
81+
82+
const borderRadius = animVal.interpolate({
83+
inputRange: [0, 1],
84+
outputRange: [
85+
(prevType?.size || 3) * props.sizeRatio * 0.5,
86+
type.size * props.sizeRatio * 0.5,
87+
],
88+
});
89+
const { activeColor } = props;
90+
91+
return (
92+
<Animated.View
93+
style={[
94+
{
95+
backgroundColor: activeColor,
96+
margin: 3 * props.sizeRatio,
97+
},
98+
{
99+
width: size,
100+
height: size,
101+
borderRadius: borderRadius,
102+
opacity: opacity,
103+
},
104+
]}
105+
/>
106+
);
107+
};
109108

110109
export default Dot;

0 commit comments

Comments
 (0)