Skip to content

Commit 03a2d49

Browse files
committed
refactor(NoticeBar): 使用Function组件重构 Class组件
1 parent d4193d0 commit 03a2d49

File tree

1 file changed

+67
-89
lines changed

1 file changed

+67
-89
lines changed
Lines changed: 67 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22
import { Animated, Easing, LayoutChangeEvent, StyleProp, Text, TextStyle, View } from 'react-native';
33

44
export interface MarqueeProps {
@@ -12,129 +12,107 @@ export interface MarqueeProps {
1212
maxWidth?: number;
1313
}
1414

15-
class Marquee extends React.PureComponent<MarqueeProps, any> {
16-
static defaultProps = {
17-
text: '',
18-
loop: false,
19-
leading: 500,
20-
trailing: 800,
21-
fps: 40,
22-
maxWidth: 1000,
23-
};
24-
25-
texts: any;
26-
left: any;
15+
type StateType = { twidth: number; width: number };
2716

28-
constructor(props: MarqueeProps) {
29-
super(props);
17+
function Marquee(props: MarqueeProps) {
18+
// const [texts, setTexts] = useState({});
19+
const [left, _setLeft] = useState(new Animated.Value(0));
20+
const [state, setState] = useState<StateType>({ twidth: 0, width: 0 });
3021

31-
this.texts = {};
32-
this.left = new Animated.Value(0);
33-
this.state = {
34-
twidth: 0,
35-
width: 0,
36-
};
22+
function tryStart(state: StateType) {
23+
if (state.twidth > state.width && state.width) {
24+
startMove();
25+
}
3726
}
3827

39-
onLayout = (e: LayoutChangeEvent) => {
40-
if (this.state.twidth) {
28+
const onLayout = (e: LayoutChangeEvent) => {
29+
if (state.twidth) {
4130
return;
4231
}
4332

44-
this.setState(
45-
{
46-
twidth: e.nativeEvent.layout.width,
47-
},
48-
() => {
49-
// onLayout may be earlier than onLayoutContainer on android, can not be sure width < twidth at that time.
50-
this.tryStart();
51-
},
52-
);
33+
const states = { ...state, twidth: e.nativeEvent.layout.width };
34+
setState(states);
35+
tryStart(states);
5336
};
5437

55-
tryStart() {
56-
if (this.state.twidth > this.state.width && this.state.width) {
57-
this.startMove();
58-
}
59-
}
60-
61-
onLayoutContainer = (e: LayoutChangeEvent) => {
62-
if (!this.state.width) {
63-
this.setState(
64-
{
65-
width: e.nativeEvent.layout.width,
66-
},
67-
() => {
68-
this.left.setValue(0);
69-
this.tryStart();
70-
},
71-
);
38+
const onLayoutContainer = (e: LayoutChangeEvent) => {
39+
if (!state.width) {
40+
const states = { ...state, width: e.nativeEvent.layout.width };
41+
setState(states);
42+
left.setValue(0);
43+
tryStart(states);
7244
}
7345
};
7446

75-
startMove = () => {
76-
const { fps = 40, loop } = this.props;
47+
const startMove = () => {
48+
const { fps = 40, loop } = props;
7749
const SPPED = (1 / fps) * 1000;
7850
// tslint:disable-next-line:no-this-assignment
79-
const { props } = this;
80-
Animated.timing(this.left, {
51+
Animated.timing(left, {
8152
toValue: 1,
82-
duration: this.state.twidth * SPPED,
53+
duration: state.twidth * SPPED,
8354
easing: Easing.linear,
8455
delay: props.leading,
8556
isInteraction: false,
8657
useNativeDriver: true,
8758
}).start(() => {
8859
if (loop) {
89-
this.moveToHeader();
60+
moveToHeader();
9061
}
9162
});
9263
};
9364

94-
moveToHeader = () => {
95-
Animated.timing(this.left, {
65+
const moveToHeader = () => {
66+
Animated.timing(left, {
9667
toValue: 0,
9768
duration: 0,
98-
delay: this.props.trailing,
69+
delay: props.trailing,
9970
isInteraction: false,
10071
useNativeDriver: true,
10172
}).start(() => {
102-
this.startMove();
73+
startMove();
10374
});
10475
};
10576

106-
render() {
107-
const { width, twidth } = this.state;
108-
const { style, text, maxWidth } = this.props;
77+
const { width, twidth } = state;
78+
const { style, text, maxWidth } = props;
10979

110-
const textChildren = (
111-
<Text onLayout={this.onLayout} numberOfLines={1} ellipsizeMode="tail" style={style}>
112-
{text}
113-
</Text>
114-
);
80+
const textChildren = (
81+
<Text onLayout={onLayout} numberOfLines={1} ellipsizeMode="tail" style={style}>
82+
{text}
83+
</Text>
84+
);
11585

116-
return (
117-
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }} onLayout={this.onLayoutContainer}>
118-
<Animated.View
119-
// tslint:disable-next-line:jsx-no-multiline-js
120-
style={{
121-
flexDirection: 'row',
122-
transform: [
123-
{
124-
translateX: this.left.interpolate({
125-
inputRange: [0, 1],
126-
outputRange: [0, -twidth + width],
127-
}),
128-
},
129-
],
130-
width: maxWidth,
131-
}}
132-
>
133-
{textChildren}
134-
</Animated.View>
135-
</View>
136-
);
137-
}
86+
return (
87+
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }} onLayout={onLayoutContainer}>
88+
<Animated.View
89+
// tslint:disable-next-line:jsx-no-multiline-js
90+
style={{
91+
flexDirection: 'row',
92+
transform: [
93+
{
94+
translateX: left.interpolate({
95+
inputRange: [0, 1],
96+
outputRange: [0, -twidth + width],
97+
}),
98+
},
99+
],
100+
width: maxWidth,
101+
}}
102+
>
103+
{textChildren}
104+
</Animated.View>
105+
</View>
106+
);
138107
}
139108

109+
Marquee.defaultProps = {
110+
text: '',
111+
loop: false,
112+
leading: 500,
113+
trailing: 800,
114+
fps: 40,
115+
maxWidth: 1000,
116+
} as MarqueeProps;
117+
140118
export default Marquee;

0 commit comments

Comments
 (0)