· 6 years ago · Aug 28, 2019, 08:10 AM
1/*
2 Component when shown fetches numbers from mock API, informs parent about total and shows fetched entries on screen.
3 Fix errors and improve code quality.
4 Use TypeScript.
5 Entries are null initially until data is fetched.
6
7 react version 16.9
8 react-native version 0.60.4
9*/
10
11import * as React from 'react';
12import { View, Text, StyleSheet, ViewStyle, TextStyle } from 'react-native';
13import { NavigationScreenProps, NavigationEventSubscription } from 'react-navigation';
14
15type Props = {
16 multiplier?: number,
17 onNewTotal: (total: number) => void,
18};
19
20type State = {
21 isVisible:boolean,
22 entries: number[],
23};
24
25interface IState {
26 [key: string]: any;
27}
28
29
30class MultiplierComponent extends React.PureComponent<Props & NavigationScreenProps<{}>, IState> {
31 focusSubscription: NavigationEventSubscription | null = null;
32
33 state: State = {
34 isVisible: false,
35 entries: [],
36 };
37
38 componentDidMount() {
39 this.focusSubscription = this.props.navigation.addListener('willFocus', this.onFocus);
40 }
41 componentWillReceiveProps(nextProps:any) {
42 if (this.props.multiplier !== nextProps.multiplier) {
43 this.notify(nextProps.multiplier);
44 }
45 }
46 shouldComponentUpdate(nextProps:any, nextState:any) {
47 return nextProps.multiplier !== this.props.multiplier
48 || nextProps.onNewTotal !== this.props.onNewTotal
49 || nextState.entries !== this.state.entries;
50 }
51
52 onFocus() {
53 this.setState({ isVisible: true });
54 this.fetch();
55 }
56 async fetch() {
57 const entries = await this.loadData();
58 this.setState({ entries });
59 this.notify();
60 }
61 loadData() {
62 return new Promise((resolve) => window.setTimeout(() => resolve([1, 2, 3, 4, 8]), 1500));
63 }
64 notify(multiplier = this.props.multiplier) {
65 let totalEven = 0;
66 for (let i = 0; i < this.state.entries.length; i++) {
67 if (this.state.entries[i] % 2 === 0) {
68 totalEven += this.state.entries[i] * multiplier;
69 }
70 }
71
72 this.props.onNewTotal(totalEven);
73 }
74
75 render() {
76 const entries = this.state.entries;
77 const isVisible = this.state.isVisible;
78
79 const containerStyles = {
80 ...styles.container,
81 ...(isVisible ? styles.containerVisible : {}),
82 };
83 if (!isVisible) return null;
84
85 return (
86 <View styles={ containerStyles }>
87 Complex multiplier view results:
88 <Text styles={ [styles.title] }>
89 Entries:
90 <View>
91 {
92 entries.forEach((entry) => <Text>{ entry }</Text>)
93 }
94 </View>
95 </Text>
96 </View>
97 );
98 }
99}
100
101interface Styles {
102 container: ViewStyle
103 title: TextStyle
104};
105
106const styles = StyleSheet.create<Styles>({
107 container: {
108 borderRadius: 4,
109 borderWidth: 0.5,
110 borderColor: 'red',
111 backgroundColor: 'silver',
112 color: 'pink',
113 opacity: 0.5,
114 },
115 containerVisible: {
116 opacity: 1,
117 },
118 title: {
119 fontSize: '19rem',
120 fontWeight: 'bold',
121 margin: '10 0 10 15',
122 },
123});
124
125export default MultiplierComponent;