From 47379d7a1e3fd66e2d562ffe1bc974a4804642f5 Mon Sep 17 00:00:00 2001 From: Maria Zadnepryanets Date: Wed, 11 Mar 2020 20:19:45 +0000 Subject: [PATCH] Lint rule react prop types addition --- .eslintrc | 2 +- components/app-text-input.js | 6 +- components/app-text.js | 25 +++--- components/button.js | 33 ++++--- components/calendar.js | 6 ++ components/chart/chart.js | 16 +++- components/chart/day-column.js | 13 +++ components/chart/dot-and-line.js | 10 +++ components/cycle-day/SymptomBox.js | 90 ++++++++++--------- components/cycle-day/select-box-group.js | 68 +++++++------- components/cycle-day/select-tab-group.js | 89 +++++++++--------- components/cycle-day/symptoms/desire.js | 2 +- components/cycle-day/symptoms/info-symptom.js | 12 ++- components/cycle-day/symptoms/note.js | 14 +-- .../cycle-day/symptoms/symptom-section.js | 4 +- components/cycle-day/symptoms/symptom-view.js | 7 +- .../cycle-day/symptoms/temperature-input.js | 4 + components/framed-segment.js | 19 ++-- components/header/index.js | 3 +- components/license.js | 7 +- components/link.js | 8 ++ components/menu/menu-item.js | 16 ++-- components/password-prompt.js | 5 ++ components/settings/settings-menu.js | 9 +- components/settings/shared/settings-button.js | 5 +- styles/index.js | 3 +- 26 files changed, 292 insertions(+), 184 deletions(-) diff --git a/.eslintrc b/.eslintrc index 761d707..7fb97d8 100644 --- a/.eslintrc +++ b/.eslintrc @@ -44,7 +44,7 @@ "no-var": "error", "prefer-const": "error", "no-trailing-spaces": "error", - "react/prop-types": 0, + "react/prop-types": 2, "max-len": [ 1, { diff --git a/components/app-text-input.js b/components/app-text-input.js index 50bf3f1..54e4a19 100644 --- a/components/app-text-input.js +++ b/components/app-text-input.js @@ -18,7 +18,11 @@ export default function AppTextInput({ style, ...props }) { } AppTextInput.propTypes = { - secureTextEntry: PropTypes.bool + autoFocus: PropTypes.bool, + onChangeText: PropTypes.func, + placeholder: PropTypes.string, + style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]), + value: PropTypes.string, } AppTextInput.defaultProps = { diff --git a/components/app-text.js b/components/app-text.js index 83e8781..e2c6210 100644 --- a/components/app-text.js +++ b/components/app-text.js @@ -1,27 +1,26 @@ import React from 'react' +import PropTypes from 'prop-types' import { Text } from 'react-native' import styles from "../styles" import Link from './link' -export default function AppText(props) { +export default function AppText({ children, onPress, numberOfLines, style}) { // we parse for links in case the text contains any return ( - - {props.children} + {children} ) } -export function SymptomSectionHeader(props) { - return ( - - {props.children} - - ) -} \ No newline at end of file +AppText.propTypes = { + children: PropTypes.node, + onPress: PropTypes.func, + numberOfLines: PropTypes.number, + style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]), +} diff --git a/components/button.js b/components/button.js index 41d5344..be06408 100644 --- a/components/button.js +++ b/components/button.js @@ -1,22 +1,31 @@ import React from 'react' +import PropTypes from 'prop-types' import { TouchableOpacity } from 'react-native' import AppText from './app-text' import styles from '../styles' -export default function Button(props) { +export default function Button({ + backgroundColor, + children, + onPress, + style, + testID +}) { return ( - - {props.children} - + {children} ) -} \ No newline at end of file +} + +Button.propTypes = { + backgroundColor: PropTypes.string, + children: PropTypes.node, + onPress: PropTypes.func, + style: PropTypes.object, + testID: PropTypes.string +} diff --git a/components/calendar.js b/components/calendar.js index 9387e0c..2340168 100644 --- a/components/calendar.js +++ b/components/calendar.js @@ -1,4 +1,5 @@ import React, { Component } from 'react' +import PropTypes from 'prop-types' import { CalendarList } from 'react-native-calendars' import { connect } from 'react-redux' @@ -13,6 +14,11 @@ import styles from '../styles/index' import nothingChanged from '../db/db-unchanged' class CalendarView extends Component { + static propTypes = { + setDate: PropTypes.func.isRequired, + navigate: PropTypes.func.isRequired + } + constructor(props) { super(props) this.bleedingDays = getBleedingDaysSortedByDate() diff --git a/components/chart/chart.js b/components/chart/chart.js index 9598552..d11131a 100644 --- a/components/chart/chart.js +++ b/components/chart/chart.js @@ -1,4 +1,5 @@ import React, { Component } from 'react' +import PropTypes from 'prop-types' import { View, FlatList, ActivityIndicator } from 'react-native' import AppLoadingView from '../app-loading' @@ -17,6 +18,11 @@ import config from '../../config' import styles from './styles' export default class CycleChart extends Component { + static propTypes = { + navigate: PropTypes.func, + end: PropTypes.bool + } + constructor(props) { super(props) this.state = {} @@ -147,12 +153,14 @@ export default class CycleChart extends Component { } } -function LoadingMoreView(props) { +function LoadingMoreView({ end }) { return ( - {!props.end && - - } + {!end && } ) } + +LoadingMoreView.propTypes = { + end: PropTypes.bool +} diff --git a/components/chart/day-column.js b/components/chart/day-column.js index fffc1fc..687b993 100644 --- a/components/chart/day-column.js +++ b/components/chart/day-column.js @@ -1,4 +1,5 @@ import React, { Component } from 'react' +import PropTypes from 'prop-types' import { TouchableOpacity } from 'react-native' import { connect } from 'react-redux' @@ -18,6 +19,18 @@ import { } from '../helpers/chart' class DayColumn extends Component { + static propTypes = { + dateString: PropTypes.string.isRequired, + chartSymptoms: PropTypes.array, + columnHeight: PropTypes.number.isRequired, + getFhmAndLtlInfo: PropTypes.func.isRequired, + navigate: PropTypes.func.isRequired, + setDate: PropTypes.func.isRequired, + symptomHeight: PropTypes.number.isRequired, + symptomRowSymptoms: PropTypes.array, + xAxisHeight: PropTypes.number + } + constructor(props) { super() diff --git a/components/chart/dot-and-line.js b/components/chart/dot-and-line.js index 21e9eeb..be5be85 100644 --- a/components/chart/dot-and-line.js +++ b/components/chart/dot-and-line.js @@ -1,10 +1,20 @@ import React, { Component } from 'react' +import PropTypes from 'prop-types' import { Path, Shape } from 'react-native/Libraries/ART/ReactNativeART' import styles from './styles' import config from '../../config' export default class DotAndLine extends Component { + static propTypes = { + exclude: PropTypes.bool, + leftY: PropTypes.number, + leftTemperatureExclude: PropTypes.bool, + rightY: PropTypes.number, + rightTemperatureExclude: PropTypes.bool, + y: PropTypes.number.isRequired + } + shouldComponentUpdate(newProps) { return Object.keys(newProps).some(key => newProps[key] != this.props[key]) } diff --git a/components/cycle-day/SymptomBox.js b/components/cycle-day/SymptomBox.js index b4af7c3..62f5df0 100644 --- a/components/cycle-day/SymptomBox.js +++ b/components/cycle-day/SymptomBox.js @@ -1,4 +1,5 @@ -import React, { Component } from 'react' +import React from 'react' +import PropTypes from 'prop-types' import { View, TouchableOpacity } from 'react-native' import AppText from '../app-text' @@ -124,47 +125,50 @@ const l = { } } -export default class SymptomBox extends Component { - getLabel = () => { - const { symptom, symptomData } = this.props - return symptomData && l[symptom](symptomData) - } - - render() { - const { symptom, onPress, disabled } = this.props - const data = this.getLabel() - const iconName = `drip-icon-${symptom}` - - const disabledStyle = disabled ? styles.symptomInFuture : null - const containerStyle = [ - styles.symptomBox, - data && styles.symptomBoxActive, - disabledStyle - ] - const titleStyle = [ - data && styles.symptomTextActive, - disabledStyle, - {fontSize: 15} - ] - const dataBoxStyle = [styles.symptomDataBox, disabledStyle] - - return ( - - - - - {symptomTitles[symptom].toLowerCase()} - - - - - {data} - - - - ) - } +const getLabel = (symptom, symptomData) => { + return symptomData && l[symptom](symptomData) } -const Icon = ({name, isActive}) => - \ No newline at end of file +export default function SymptomBox( + { disabled, onPress, symptom, symptomData }) { + + const data = getLabel(symptom, symptomData) + const iconName = `drip-icon-${symptom}` + + const disabledStyle = disabled ? styles.symptomInFuture : null + const containerStyle = [ + styles.symptomBox, + data && styles.symptomBoxActive, + disabledStyle + ] + const titleStyle = [ + data && styles.symptomTextActive, + disabledStyle, + {fontSize: 15} + ] + const dataBoxStyle = [styles.symptomDataBox, disabledStyle] + const iconColor = data ? 'white' : 'black' + + return ( + + + + + {symptomTitles[symptom].toLowerCase()} + + + + + {data} + + + + ) +} + +SymptomBox.propTypes = { + disabled: PropTypes.bool.isRequired, + onPress: PropTypes.func.isRequired, + symptom: PropTypes.string.isRequired, + symptomData: PropTypes.object +} \ No newline at end of file diff --git a/components/cycle-day/select-box-group.js b/components/cycle-day/select-box-group.js index 3ff1f58..ee64d00 100644 --- a/components/cycle-day/select-box-group.js +++ b/components/cycle-day/select-box-group.js @@ -1,34 +1,38 @@ -import React, { Component } from 'react' -import { - View, - TouchableOpacity, -} from 'react-native' -import styles from '../../styles' +import React from 'react' +import PropTypes from 'prop-types' +import { View, TouchableOpacity } from 'react-native' + import AppText from '../app-text' -export default class SelectBoxGroup extends Component { - render() { - return ( - - {Object.keys(this.props.labels).map(key => { - const style = [styles.selectBox] - const textStyle = [] - if (this.props.optionsState[key]) { - style.push(styles.selectBoxActive) - textStyle.push(styles.selectBoxTextActive) - } - return ( - this.props.onSelect(key)} - key={key} - > - - {this.props.labels[key]} - - - ) - })} - - ) - } -} \ No newline at end of file +import styles from '../../styles' + +export default function SelectBoxGroup({ labels, onSelect, optionsState }) { + return ( + + {Object.keys(labels).map(key => { + const style = [styles.selectBox] + const textStyle = [] + if (optionsState[key]) { + style.push(styles.selectBoxActive) + textStyle.push(styles.selectBoxTextActive) + } + return ( + onSelect(key)} + key={key} + > + + {labels[key]} + + + ) + })} + + ) +} + +SelectBoxGroup.propTypes = { + labels: PropTypes.object.isRequired, + onSelect: PropTypes.func.isRequired, + optionsState: PropTypes.object.isRequired +} diff --git a/components/cycle-day/select-tab-group.js b/components/cycle-day/select-tab-group.js index 63c0536..a8fffc6 100644 --- a/components/cycle-day/select-tab-group.js +++ b/components/cycle-day/select-tab-group.js @@ -1,47 +1,50 @@ -import React, { Component } from 'react' -import { - View, - TouchableOpacity, -} from 'react-native' -import styles from '../../styles' +import React from 'react' +import PropTypes from 'prop-types' +import { View, TouchableOpacity } from 'react-native' + import AppText from '../app-text' -export default class SelectTabGroup extends Component { - render() { - const { buttons, onSelect } = this.props - return ( - - { - buttons.map(({ label, value }, i) => { - let firstOrLastStyle - if (i === buttons.length - 1) { - firstOrLastStyle = styles.selectTabLast - } else if (i === 0) { - firstOrLastStyle = styles.selectTabFirst - } - let activeStyle - const isActive = value === this.props.active - if (isActive) activeStyle = styles.selectTabActive - return ( - onSelect(isActive ? null : value)} - key={i} - activeOpacity={1} - > - - - {label} - +import styles from '../../styles' + +export default function SelectTabGroup({ active, buttons, onSelect }) { + return ( + + { + buttons.map(({ label, value }, i) => { + let firstOrLastStyle + if (i === buttons.length - 1) { + firstOrLastStyle = styles.selectTabLast + } else if (i === 0) { + firstOrLastStyle = styles.selectTabFirst + } + let activeStyle + const isActive = value === active + if (isActive) activeStyle = styles.selectTabActive + return ( + onSelect(isActive ? null : value)} + key={i} + activeOpacity={1} + > + + + {label} - - ) - }) - } - - ) - } + + + ) + }) + } + + ) +} + +SelectTabGroup.propTypes = { + active: PropTypes.number, + buttons: PropTypes.array.isRequired, + onSelect: PropTypes.func.isRequired } \ No newline at end of file diff --git a/components/cycle-day/symptoms/desire.js b/components/cycle-day/symptoms/desire.js index 1898366..de05f52 100644 --- a/components/cycle-day/symptoms/desire.js +++ b/components/cycle-day/symptoms/desire.js @@ -21,7 +21,7 @@ class Desire extends Component { const symptom = 'desire' const { cycleDay } = props - const defaultSymptomData = { value: '' } + const defaultSymptomData = { value: null } const symptomData = cycleDay && cycleDay[symptom] ? cycleDay[symptom] : defaultSymptomData diff --git a/components/cycle-day/symptoms/info-symptom.js b/components/cycle-day/symptoms/info-symptom.js index 887b229..93820e2 100644 --- a/components/cycle-day/symptoms/info-symptom.js +++ b/components/cycle-day/symptoms/info-symptom.js @@ -1,22 +1,28 @@ import React from 'react' +import PropTypes from 'prop-types' import { ScrollView, View, TouchableOpacity } from 'react-native' import Icon from 'react-native-vector-icons/SimpleLineIcons' import AppText from '../../app-text' import labels from '../../../i18n/en/symptom-info.js' import styles, {iconStyles} from '../../../styles/index' -export default function InfoSymptom(props) { +export default function InfoSymptom({ close, symptom }) { return ( - + - {labels[props.symptom].text} + {labels[symptom].text} ) } + +InfoSymptom.propTypes = { + close: PropTypes.func.isRequired, + symptom: PropTypes.string.isRequired +} diff --git a/components/cycle-day/symptoms/note.js b/components/cycle-day/symptoms/note.js index 17cfef1..4dd7866 100644 --- a/components/cycle-day/symptoms/note.js +++ b/components/cycle-day/symptoms/note.js @@ -1,4 +1,5 @@ import React, { Component } from 'react' +import PropTypes from 'prop-types' import { TextInput } from 'react-native' import SymptomSection from './symptom-section' @@ -9,6 +10,11 @@ import SymptomView from './symptom-view' import { saveSymptom } from '../../../db' class Note extends Component { + static propTypes = { + cycleDay: PropTypes.object.isRequired, + date: PropTypes.string.isRequired + } + constructor(props) { super(props) const symptom = 'note' @@ -41,16 +47,12 @@ class Note extends Component { values={this.state} date={this.props.date} > - + { - this.setState({ value: val }) - }} + onChangeText={(val) => { this.setState({ value: val })}} value={this.state.value} testID='noteInput' /> diff --git a/components/cycle-day/symptoms/symptom-section.js b/components/cycle-day/symptoms/symptom-section.js index 0728454..92192df 100644 --- a/components/cycle-day/symptoms/symptom-section.js +++ b/components/cycle-day/symptoms/symptom-section.js @@ -1,6 +1,6 @@ import React, { Component } from 'react' import { View } from 'react-native' -import AppText, { SymptomSectionHeader } from '../../app-text' +import AppText from '../../app-text' import styles from '../../../styles' export default class SymptomSection extends Component { @@ -16,7 +16,7 @@ export default class SymptomSection extends Component { return ( { p.header && - {p.header} + {p.header} }
diff --git a/components/cycle-day/symptoms/temperature-input.js b/components/cycle-day/symptoms/temperature-input.js index 2bcc39e..cc0dbd9 100644 --- a/components/cycle-day/symptoms/temperature-input.js +++ b/components/cycle-day/symptoms/temperature-input.js @@ -102,3 +102,7 @@ const OutOfRangeWarning = ({ temperature }) => { return {warningMsg} } + +OutOfRangeWarning.propTypes = { + temperature: PropTypes.string.isRequired +} diff --git a/components/framed-segment.js b/components/framed-segment.js index 800c564..49bce23 100644 --- a/components/framed-segment.js +++ b/components/framed-segment.js @@ -5,21 +5,24 @@ import { View } from 'react-native' import AppText from './app-text' import styles from '../styles' -const FramedSegment = ({children, ...props}) => { - const style = [styles.framedSegment, props.style] - if (props.last) style.push(styles.framedSegmentLast) +const FramedSegment = ({ children, last, style, title }) => { + const viewStyle = [styles.framedSegment, style] + if (last) viewStyle.push(styles.framedSegmentLast) return ( - - { - props.title - && {props.title} - } + + {title && {title}} {children} ) } FramedSegment.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]), + last: PropTypes.bool, + style: PropTypes.object, title: PropTypes.string } diff --git a/components/header/index.js b/components/header/index.js index d96856a..885eec3 100644 --- a/components/header/index.js +++ b/components/header/index.js @@ -29,7 +29,8 @@ export default function Header({ Header.propTypes = { handleBack: PropTypes.func, + handleDelete: PropTypes.func, handleNext: PropTypes.func, - title: PropTypes.string, subtitle: PropTypes.string, + title: PropTypes.string.isRequired } diff --git a/components/license.js b/components/license.js index 5a95ad1..b433063 100644 --- a/components/license.js +++ b/components/license.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { ScrollView, View, BackHandler } from 'react-native' import AppText from './app-text' import { shared } from '../i18n/en/labels' @@ -36,4 +37,8 @@ export default function License({setLicense}) { ) -} \ No newline at end of file +} + +License.propTypes = { + setLicense: PropTypes.func.isRequired +} diff --git a/components/link.js b/components/link.js index d0b9a83..caea792 100644 --- a/components/link.js +++ b/components/link.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import Hyperlink from 'react-native-hyperlink' import styles from '../styles' import links from '../i18n/en/links' @@ -15,6 +16,13 @@ export default function Link(props) { ) } +Link.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]) +} + function replaceUrlWithText(url) { const link = Object.values(links).find(l => l.url === url) return (link && link.text) || url diff --git a/components/menu/menu-item.js b/components/menu/menu-item.js index cf59c0e..8dc1bcd 100644 --- a/components/menu/menu-item.js +++ b/components/menu/menu-item.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { Text, TouchableOpacity } from 'react-native' import styles, { iconStyles, secondaryColor } from '../../styles' @@ -11,13 +12,11 @@ const menuTitlesLowerCase = Object.keys(menuTitles).reduce((acc, curr) => { return acc }, {}) -const MenuItem = ({ icon, label, active, onPress }) => { +export default function MenuItem({ active, icon, label, onPress }) { const styleActive = active ? { color: secondaryColor } : null + return ( - + { ) } -export default MenuItem \ No newline at end of file +MenuItem.propTypes = { + active: PropTypes.bool, + icon: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + onPress: PropTypes.func.isRequired +} \ No newline at end of file diff --git a/components/password-prompt.js b/components/password-prompt.js index 356a699..b2b7af4 100644 --- a/components/password-prompt.js +++ b/components/password-prompt.js @@ -1,4 +1,5 @@ import React, { Component } from 'react' +import PropTypes from 'prop-types' import { View, TextInput, TouchableOpacity, Alert } from 'react-native' import nodejs from 'nodejs-mobile-react-native' import { saveEncryptionFlag } from '../local-storage' @@ -9,6 +10,10 @@ import { passwordPrompt as labels, shared, menuTitles } from '../i18n/en/labels' import { requestHash, deleteDbAndOpenNew, openDb } from '../db' export default class PasswordPrompt extends Component { + static propTypes = { + enableShowApp: PropTypes.func.isRequired + } + constructor(props) { super(props) this.state = { diff --git a/components/settings/settings-menu.js b/components/settings/settings-menu.js index a622a1d..f6b6bc2 100644 --- a/components/settings/settings-menu.js +++ b/components/settings/settings-menu.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { TouchableOpacity, ScrollView } from 'react-native' import { connect } from 'react-redux' @@ -21,7 +22,7 @@ const menu = [ {title: labels.license, component: 'License'} ] -const SettingsMenu = (props) => { +const SettingsMenu = ({ navigate }) => { return ( { menu.map(menuItem)} @@ -33,7 +34,7 @@ const SettingsMenu = (props) => { props.navigate(item.component)} + onPress={() => navigate(item.component)} > {item.title.toLowerCase()} @@ -41,6 +42,10 @@ const SettingsMenu = (props) => { } } +SettingsMenu.propTypes = { + navigate: PropTypes.func.isRequired +} + const mapDispatchToProps = (dispatch) => { return({ navigate: (page) => dispatch(navigate(page)), diff --git a/components/settings/shared/settings-button.js b/components/settings/shared/settings-button.js index 00bc8ed..94aa210 100644 --- a/components/settings/shared/settings-button.js +++ b/components/settings/shared/settings-button.js @@ -28,8 +28,11 @@ const SettingsButton = ({ children, style, secondary, ...props }) => { } SettingsButton.propTypes = { + children: PropTypes.node, + disabled: PropTypes.bool, onPress: PropTypes.func.isRequired, - disabled: PropTypes.bool + secondary: PropTypes.bool, + style: PropTypes.object } export default SettingsButton \ No newline at end of file diff --git a/styles/index.js b/styles/index.js index 1b9bb4f..e54b8bb 100644 --- a/styles/index.js +++ b/styles/index.js @@ -157,7 +157,8 @@ export default StyleSheet.create({ }, symptomViewHeading: { fontWeight: 'bold', - fontFamily: textFontBold + fontFamily: textFontBold, + flex: 1 }, symptomSection: { marginBottom: 10