将旧版React 0.59.X代码升级到0.63.X

时间:2020-08-11 15:54:44

标签: reactjs react-native redux react-redux

我正在尝试将旧版React Native应用程序(也使用Redux)升级到最新版本,并且遵循以下准则:

这是旧代码库的示例:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { View, Text } from 'react-native'
import { Colors } from '../../Themes'
import FontAwesome from 'react-native-vector-icons/FontAwesome'
import Octicons from 'react-native-vector-icons/Octicons'
import Feather from 'react-native-vector-icons/Feather'
import AntDesign from 'react-native-vector-icons/AntDesign'
import StatusLabel from '../WcGlobals/StatusLabel'
import OrderItemsList from '../WcGlobals/OrderItemsList'
import CurrencySymbols from '../../Constants/CurrencySymbols'
import FullScreenLoader from '../FullScreenLoader'
import { CapabilitiesSelectors } from '../../Redux/CapabilitiesRedux'
import moment from 'moment'
import Menu, {
  MenuTrigger,
  MenuOptions,
  MenuOption,
  renderers
} from 'react-native-popup-menu'

import styles from './Styles/OrderListItemStyle'

const { SlideInMenu } = renderers

class OrderListItem extends Component {
  // // Prop type warnings
  static propTypes = {
    order: PropTypes.object,
    index: PropTypes.number,
    capabilities: PropTypes.object
  }

  statuses = [
    { label: 'On Hold', value: 'on-hold' },
    { label: 'Processing', value: 'processing' },
    { label: 'Completed', value: 'completed' },
    { label: 'Pending', value: 'pending' }
  ]

  getOrderStatus = () => {
    const { order } = this.props
    return this.statuses.filter(
      ({ value }) => {
        if (order.status === 'processing') { return value === 'completed' }
        if (order.status === 'completed') { return false }
        if (order.status === 'on-hold') { return value === 'completed' || value === 'processing' }
        if (order.status === 'pending') { return value !== order.status }
      }
    )
  }

  onSelect = (value) => {
    const { onUpdate, order } = this.props
    onUpdate(order.id, value)
  }

  render () {
    if (this.props.updating) {
      return (<FullScreenLoader />)
    }
    const statuses = this.getOrderStatus()
    // console.log(statuses);
    const { order, index } = this.props
    const date = moment(order.date_created).format('DDMMM YYYY')
    const time = moment(order.date_created).format('hh:mmA')
    if (!this.props.capabilities.order_status_update && statuses.length !== 0) {
      return (
        <Menu name={`order-status-${this.props.index}`} renderer={SlideInMenu} style={this.props.index ? styles.listItemContainer : styles.listItemContainerFirst} onSelect={this.onSelect}>
          <MenuTrigger>
            <View style={styles.listItemRow}>
              <View style={styles.orderNameStatusContainer}>
                <View style={styles.orderNoCustContainer}>
                  <Text style={styles.orderName}>{'#' + order.id}</Text>
                  { (order.customer_id)
                    ? (<Text style={styles.orderCustomer}>{' (By ' + order.billing.first_name + ' ' + order.billing.last_name + ')' }</Text>)
                    : (<Text style={styles.orderCustomer}>{' (By Guest)' }</Text>)
                  }
                </View>
                <View style={styles.orderStatusItemsContainer}>
                  <StatusLabel status={order.status} />
                </View>
              </View>
              <View style={styles.orderProductContainer}>
                <Octicons size={17} name={'package'} color={Colors.secondaryColor} />
                <OrderItemsList items={order.line_items} />
              </View>
              <View style={[styles.orderDateContainer]}>
                <AntDesign size={16.5} name={'clockcircleo'} color={Colors.secondaryColor} /><Text style={styles.orderDate}>{ date + ' | ' + time }</Text>
                <View style={styles.orderCommissionContainer}>
                  <FontAwesome size={17} name={'money'} color={Colors.secondaryColor} /><Text style={styles.orderCommission}> Earnings: {CurrencySymbols[order.currency]}{Math.round(order.vendor_order_details.total_commission * 100) / 100 }</Text>
                </View>
              </View>
            </View>
          </MenuTrigger>
          <MenuOptions customStyles={{ optionText: styles.slideInOption }}>
            <MenuOption key={'00'} value={''} disabled disableTouchable text={'Tap any one of the options below to change the order status'} />
            {statuses.map(({ label, value }) => (<MenuOption key={value} value={value} text={label} />))}
          </MenuOptions>
        </Menu>
      )
    } else {
      return (
        <View style={this.props.index ? styles.listItemContainer : styles.listItemContainerFirst} >
          <View style={styles.listItemRow}>
            <View style={styles.orderNameStatusContainer}>
              <View style={styles.orderNoCustContainer}>
                <Text style={styles.orderName}>{'#' + order.id}</Text>
                { (order.customer_id)
                  ? (<Text style={styles.orderCustomer}>{' (By ' + order.billing.first_name + ' ' + order.billing.last_name + ')' }</Text>)
                  : (<Text style={styles.orderCustomer}>{' (By Guest)' }</Text>)
                }
              </View>
              <View style={styles.orderStatusItemsContainer}>
                <StatusLabel status={order.status} />
              </View>

            </View>
            <View style={styles.orderProductContainer}>
              <Octicons size={17} name={'package'} color={Colors.secondaryColor} /><OrderItemsList items={order.line_items} />
            </View>
            <View style={[styles.orderDateContainer]}>
              <AntDesign size={16.5} name={'clockcircleo'} color={Colors.secondaryColor} /><Text style={styles.orderDate}>{ date + ' | ' + time }</Text>
              <View style={styles.orderCommissionContainer}>
                <FontAwesome size={17} name={'money'} color={Colors.secondaryColor} /><Text style={styles.orderCommission}>Earnings: {CurrencySymbols[order.currency]}{Math.round(order.vendor_order_details.total_commission * 100) / 100 }</Text>
              </View>
            </View>
          </View>
        </View>
      )
    }
  }
}

const mapStateToProps = (state) => {
  return {
    capabilities: CapabilitiesSelectors.getData(state)
  }
}

export default compose(
  connect(mapStateToProps)
)(OrderListItem)

我正在尝试遵循本指南:https://react-native-community.github.io/upgrade-helper/?from=0.59.5&to=0.63.2 到目前为止,这是我想出的:

import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import {Platform, StyleSheet, Text, View} from 'react-native';
import { Colors } from '../../Themes'
import FontAwesome from 'react-native-vector-icons/FontAwesome'
import Octicons from 'react-native-vector-icons/Octicons'
import Feather from 'react-native-vector-icons/Feather'
import AntDesign from 'react-native-vector-icons/AntDesign'
import StatusLabel from '../WcGlobals/StatusLabel'
import OrderItemsList from '../WcGlobals/OrderItemsList'
import CurrencySymbols from '../../Constants/CurrencySymbols'
import FullScreenLoader from '../FullScreenLoader'
import { CapabilitiesSelectors } from '../../Redux/CapabilitiesRedux'
import moment from 'moment'
import Menu, {
  MenuTrigger,
  MenuOptions,
  MenuOption,
  renderers
} from 'react-native-popup-menu'

import styles from './Styles/OrderListItemStyle'

const { SlideInMenu } = renderers

const OrderListItem = ({order,index,capabilities}) => {
//class OrderListItem extends Component {
  // // Prop type warnings
  OrderListItem.propTypes = {
    order: PropTypes.object,
    index: PropTypes.number,
    capabilities: PropTypes.object
  }

  statuses = [
    { label: 'On Hold', value: 'on-hold' },
    { label: 'Processing', value: 'processing' },
    { label: 'Completed', value: 'completed' },
    { label: 'Pending', value: 'pending' }
  ]

  getOrderStatus = () => {
    const { order } = this.props
    return this.statuses.filter(
      ({ value }) => {
        if (order.status === 'processing') { return value === 'completed' }
        if (order.status === 'completed') { return false }
        if (order.status === 'on-hold') { return value === 'completed' || value === 'processing' }
        if (order.status === 'pending') { return value !== order.status }
      }
    )
  }

  onSelect = (value) => {
    const { onUpdate, order } = this.props
    onUpdate(order.id, value)
  }

  render () {
    if (this.props.updating) {
      return (<FullScreenLoader />)
    }
    const statuses = this.getOrderStatus()
    // console.log(statuses);
    const { order, index } = this.props
    const date = moment(order.date_created).format('DDMMM YYYY')
    const time = moment(order.date_created).format('hh:mmA')
    if (!this.props.capabilities.order_status_update && statuses.length !== 0) {
      return (
        <Menu name={`order-status-${this.props.index}`} renderer={SlideInMenu} style={this.props.index ? styles.listItemContainer : styles.listItemContainerFirst} onSelect={this.onSelect}>
          <MenuTrigger>
            <View style={styles.listItemRow}>
              <View style={styles.orderNameStatusContainer}>
                <View style={styles.orderNoCustContainer}>
                  <Text style={styles.orderName}>{'#' + order.id}</Text>
                  { (order.customer_id)
                    ? (<Text style={styles.orderCustomer}>{' (By ' + order.billing.first_name + ' ' + order.billing.last_name + ')' }</Text>)
                    : (<Text style={styles.orderCustomer}>{' (By Guest)' }</Text>)
                  }
                </View>
                <View style={styles.orderStatusItemsContainer}>
                  <StatusLabel status={order.status} />
                </View>
              </View>
              <View style={styles.orderProductContainer}>
                <Octicons size={17} name={'package'} color={Colors.secondaryColor} />
                <OrderItemsList items={order.line_items} />
              </View>
              <View style={[styles.orderDateContainer]}>
                <AntDesign size={16.5} name={'clockcircleo'} color={Colors.secondaryColor} /><Text style={styles.orderDate}>{ date + ' | ' + time }</Text>
                <View style={styles.orderCommissionContainer}>
                  <FontAwesome size={17} name={'money'} color={Colors.secondaryColor} /><Text style={styles.orderCommission}> Earnings: {CurrencySymbols[order.currency]}{Math.round(order.vendor_order_details.total_commission * 100) / 100 }</Text>
                </View>
              </View>
            </View>
          </MenuTrigger>
          <MenuOptions customStyles={{ optionText: styles.slideInOption }}>
            <MenuOption key={'00'} value={''} disabled disableTouchable text={'Tap any one of the options below to change the order status'} />
            {statuses.map(({ label, value }) => (<MenuOption key={value} value={value} text={label} />))}
          </MenuOptions>
        </Menu>
      )
    } else {
      return (
        <View style={this.props.index ? styles.listItemContainer : styles.listItemContainerFirst} >
          <View style={styles.listItemRow}>
            <View style={styles.orderNameStatusContainer}>
              <View style={styles.orderNoCustContainer}>
                <Text style={styles.orderName}>{'#' + order.id}</Text>
                { (order.customer_id)
                  ? (<Text style={styles.orderCustomer}>{' (By ' + order.billing.first_name + ' ' + order.billing.last_name + ')' }</Text>)
                  : (<Text style={styles.orderCustomer}>{' (By Guest)' }</Text>)
                }
              </View>
              <View style={styles.orderStatusItemsContainer}>
                <StatusLabel status={order.status} />
              </View>

            </View>
            <View style={styles.orderProductContainer}>
              <Octicons size={17} name={'package'} color={Colors.secondaryColor} /><OrderItemsList items={order.line_items} />
            </View>
            <View style={[styles.orderDateContainer]}>
              <AntDesign size={16.5} name={'clockcircleo'} color={Colors.secondaryColor} /><Text style={styles.orderDate}>{ date + ' | ' + time }</Text>
              <View style={styles.orderCommissionContainer}>
                <FontAwesome size={17} name={'money'} color={Colors.secondaryColor} /><Text style={styles.orderCommission}>Earnings: {CurrencySymbols[order.currency]}{Math.round(order.vendor_order_details.total_commission * 100) / 100 }</Text>
              </View>
            </View>
          </View>
        </View>
      )
    }
  }
}

const mapStateToProps = (state) => {
  return {
    capabilities: CapabilitiesSelectors.getData(state)
  }
}

export default compose(
  connect(mapStateToProps)
)(OrderListItem)

现在,运行我的应用程序时出现以下错误:

 ERROR    [Error: TransformError SyntaxError: /App/Components/OrderListing/OrderListItem.js: Unexpected token, expected ";" (61:12)

  59 |   }
  60 | 
> 61 |   render () {
     |             ^
  62 |     if (this.props.updating) {
  63 |       return (<FullScreenLoader />)
  64 |     }]

有什么办法解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

类组件在当前版本的React中仍然存在,没有理由用功能组件完全替换它们。但是,如果要执行此操作,则必须意识到该组件是render函数。您不能在功能组件内部拥有属性和方法。这是一个函数,因此您将需要变量和语句。

此外,您根本不应使用this

基本形式为:

const OrderListItem = props => {
   return ...
};

OrderListItem.propTypes = { ... };

完整地,它应该类似于以下内容(未经测试)。

const OrderListItem = props => {
  const statuses = [
    { label: 'On Hold', value: 'on-hold' },
    { label: 'Processing', value: 'processing' },
    { label: 'Completed', value: 'completed' },
    { label: 'Pending', value: 'pending' }
  ];

  const getOrderStatus = () => {
    const { order } = props
    return statuses.filter(
      ({ value }) => {
        if (order.status === 'processing') { return value === 'completed' }
        if (order.status === 'completed') { return false }
        if (order.status === 'on-hold') { return value === 'completed' || value === 'processing' }
        if (order.status === 'pending') { return value !== order.status }
      }
    )
  };

  const onSelect = (value) => {
    const { onUpdate, order } = props;
    onUpdate(order.id, value)
  };

  if (props.updating) {
    return (<FullScreenLoader />)
  }

    const statuses = getOrderStatus()
    // console.log(statuses);
    const { order, index } = props
    const date = moment(order.date_created).format('DDMMM YYYY')
    const time = moment(order.date_created).format('hh:mmA')
    if (!props.capabilities.order_status_update && statuses.length !== 0) {
      return (
        <Menu name={`order-status-${props.index}`} renderer={SlideInMenu} style={props.index ? styles.listItemContainer : styles.listItemContainerFirst} onSelect={onSelect}>
          <MenuTrigger>
            <View style={styles.listItemRow}>
              <View style={styles.orderNameStatusContainer}>
                <View style={styles.orderNoCustContainer}>
                  <Text style={styles.orderName}>{'#' + order.id}</Text>
                  { (order.customer_id)
                    ? (<Text style={styles.orderCustomer}>{' (By ' + order.billing.first_name + ' ' + order.billing.last_name + ')' }</Text>)
                    : (<Text style={styles.orderCustomer}>{' (By Guest)' }</Text>)
                  }
                </View>
                <View style={styles.orderStatusItemsContainer}>
                  <StatusLabel status={order.status} />
                </View>
              </View>
              <View style={styles.orderProductContainer}>
                <Octicons size={17} name={'package'} color={Colors.secondaryColor} />
                <OrderItemsList items={order.line_items} />
              </View>
              <View style={[styles.orderDateContainer]}>
                <AntDesign size={16.5} name={'clockcircleo'} color={Colors.secondaryColor} /><Text style={styles.orderDate}>{ date + ' | ' + time }</Text>
                <View style={styles.orderCommissionContainer}>
                  <FontAwesome size={17} name={'money'} color={Colors.secondaryColor} /><Text style={styles.orderCommission}> Earnings: {CurrencySymbols[order.currency]}{Math.round(order.vendor_order_details.total_commission * 100) / 100 }</Text>
                </View>
              </View>
            </View>
          </MenuTrigger>
          <MenuOptions customStyles={{ optionText: styles.slideInOption }}>
            <MenuOption key={'00'} value={''} disabled disableTouchable text={'Tap any one of the options below to change the order status'} />
            {statuses.map(({ label, value }) => (<MenuOption key={value} value={value} text={label} />))}
          </MenuOptions>
        </Menu>
      )
    } else {
      return (
        <View style={props.index ? styles.listItemContainer : styles.listItemContainerFirst} >
          <View style={styles.listItemRow}>
            <View style={styles.orderNameStatusContainer}>
              <View style={styles.orderNoCustContainer}>
                <Text style={styles.orderName}>{'#' + order.id}</Text>
                { (order.customer_id)
                  ? (<Text style={styles.orderCustomer}>{' (By ' + order.billing.first_name + ' ' + order.billing.last_name + ')' }</Text>)
                  : (<Text style={styles.orderCustomer}>{' (By Guest)' }</Text>)
                }
              </View>
              <View style={styles.orderStatusItemsContainer}>
                <StatusLabel status={order.status} />
              </View>

            </View>
            <View style={styles.orderProductContainer}>
              <Octicons size={17} name={'package'} color={Colors.secondaryColor} /><OrderItemsList items={order.line_items} />
            </View>
            <View style={[styles.orderDateContainer]}>
              <AntDesign size={16.5} name={'clockcircleo'} color={Colors.secondaryColor} /><Text style={styles.orderDate}>{ date + ' | ' + time }</Text>
              <View style={styles.orderCommissionContainer}>
                <FontAwesome size={17} name={'money'} color={Colors.secondaryColor} /><Text style={styles.orderCommission}>Earnings: {CurrencySymbols[order.currency]}{Math.round(order.vendor_order_details.total_commission * 100) / 100 }</Text>
              </View>
            </View>
          </View>
        </View>
      )
  }
}

OrderListItem.propTypes = {
  order: PropTypes.object,
  index: PropTypes.number,
  capabilities: PropTypes.object
};


const mapStateToProps = (state) => {
  return {
    capabilities: CapabilitiesSelectors.getData(state)
  }
}

export default compose(
  connect(mapStateToProps)
)(OrderListItem)

当然,现在您以前的一些方法毫无意义,例如getOrderStatus可以是:

const statuses = (() => {
    const { order } = this.props
    return statuses.filter(
      ({ value }) => {
        if (order.status === 'processing') { return value === 'completed' }
        if (order.status === 'completed') { return false }
        if (order.status === 'on-hold') { return value === 'completed' || value === 'processing' }
        if (order.status === 'pending') { return value !== order.status }
      }
    )
  })();

(请注意,这只是一个匿名闭包,应立即调用。通常,与switch-case相比,order.status会更好。)

您还可以将帮助程序方法完全移出功能参数,而不是仅将必需的参数传递给props。这将使它们更易于调试和维护。