【问题标题】:Upgrade legacy React 0.59.X code to 0.63.X将旧版 React 0.59.X 代码升级到 0.63.X
【发布时间】:2020-08-12 00:41:10
【问题描述】:

我正在尝试将旧版 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 |     }]

知道如何解决这个问题吗?

【问题讨论】:

  • 您在无效 JavaScript 中迁移的代码。与 React 无关。关于如何将类组件转换为函数组件有很多答案。 Just follow 其中任何一个。另外,我不明白你为什么将 React 迁移与将类更改为函数相结合。
  • 顺便说一句,类组件仍然存在。没有理由转换为功能组件。

标签: reactjs react-native redux react-redux


【解决方案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-caseorder.status 更有效)。

您还可以将辅助方法完全移出功能参数,不传递它们props,而只传递必要的参数。这将使它们更易于调试和维护。

【讨论】:

    猜你喜欢
    • 2019-11-10
    • 2020-10-28
    • 2020-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多