luyx2412
5/24/2018 - 3:31 AM

improve performance note React Native

improve performance note React Native

/**
 * Please install https://github.com/expo/babel-preset-expo to use decorators javascript
 * And add to .babelrc
 */
{
  "presets": ["babel-preset-expo"],
  "env": {
    "production": {
      "plugins": ["transform-remove-console"]
    }
  }
}
/**
 * Stateless component to improve performance
 * Shoule be add propTypes to check validate props
 */
import React from 'react'
import PropTypes from 'prop-types'
// import { Image } from 'react-native'
import FastImage from 'react-native-fast-image'

const ImageCache = ({ style, uri }) => {
  return (
    <FastImage
      style={style}
      source={{ uri, priority: FastImage.priority.normal }}
      // resizeMode={FastImage.resizeMode.contain}
    />
  )
}

ImageCache.propTypes = {
  style: PropTypes.any,
  uri: PropTypes.any,
}

export default ImageCache
/**
 * Should be use PureComponent to avoid re-render many times --> auto compare if changed re-render component
 * And If using eslint which will show warning about Pure Component
 */
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { View, Text, TouchableWithoutFeedback, Image } from 'react-native'
import { Languages, Tools } from '@common'
import styles from './styles'

export default class UserProfileHeader extends PureComponent {
  //   constructor(props) {
  //     super(props)
  //   }
  static propTypes = {
    onLogin: PropTypes.func.isRequired,
    onLogout: PropTypes.func.isRequired,
    user: PropTypes.object,
  }

  loginHandle = () => {
    if (this.props.user.name === Languages.Guest) {
      this.props.onLogin()
    } else {
      this.props.onLogout()
    }
  }

  render() {
    const { user } = this.props
    const avatar = Tools.getAvatar(user)
    return (
      <View style={styles.container}>
        <View style={styles.header}>
          <Image source={avatar} style={styles.avatar} />
          <View style={styles.textContainer}>
            <Text style={styles.fullName}>{user.name}</Text>
            <Text style={styles.address}>{user ? user.address : ''}</Text>

            <TouchableWithoutFeedback onPress={this.loginHandle}>
              <Text style={styles.loginText}>
                {user.name === Languages.Guest
                  ? Languages.Login
                  : Languages.Logout}
              </Text>
            </TouchableWithoutFeedback>
          </View>
        </View>
      </View>
    )
  }
}
/**
 * Show loading to avoid render unnecessary and improve UX
 */
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { View, Text } from 'react-native'
import { Loading } from '@components'

export default class Home extends Component {
  static propTypes = {
    data: PropTypes.object,
    isLoading: PropTypes.bool.isLoading
  }

  static defaultProps = {
    isLoading: false
  }

  render() {
    if (this.props.isLoading || !this.props.data) return <Loading />

    return (
      <View>
        <Text>{this.props.data.name}</Text>
      </View>
    )  
  }
}
{
  "printWidth": 80,
  "parser": "babylon",
  "useTabs": false,
  "tabWidth": 2,
  "singleQuote": true,
  "jsxBracketSameLine": true,
  "arrowParens": "always",
  "insertPragma": true,
  "trailingComma": "es5",
  "filepath": "App/**/*.js"
}
{
    "parser": "babel-eslint",
    "extends": ["airbnb", "prettier"],
    "parserOptions": {
      "ecmaFeatures": {
        "experimentalObjectRestSpread": true,
        "jsx": true,
        "modules": true
      },
      "ecmaVersion": 7,
      "sourceType": "module"
    },
    "plugins": ["import"],
    "ecmaFeatures": {
      "jsx": true
    },
    "globals": {
      "expect": true,
      "setupTest": true,
      "fetch": true,
      "__DEV__": true
    },
    "env": {
      "es6": true,
      "mocha": true
    },
    "rules": {
      "semi": [2, "always"]
      "react/jsx-closing-bracket-location": 0,
      "import/no-extraneous-dependencies": 0,
      "global-require": 0,
      "new-cap": [
        2,
        {
          "newIsCap": true,
          "capIsNew": false
        }
      ],
      "max-len": [1, 160, 2],
      "arrow-body-style": 0,
      "class-methods-use-this": 0,
      "imports-first": 0,
      "react/jsx-filename-extension": [
        1,
        {
          "extensions": [".js", ".jsx"]
        }
      ],
      "no-underscore-dangle": 0,
      "no-use-before-define": 0,
      "react/forbid-prop-types": 0,
      "no-return-assign": [2, "except-parens"],
      "generator-star-spacing": 0,
      "import/prefer-default-export": 0,
      "react/jsx-wrap-multilines": 0,
      "arrow-parens": 0,
      "react/sort-comp": 0,
      "react/require-default-props": 0,
      "react/jsx-indent": 0,
      "import/extensions": "off",
      "import/no-unresolved": "off",
      "react/no-unescaped-entities": 0,
      "import/no-named-as-default": 0,
      "no-case-declarations": 0,
      "no-nested-ternary": 0,
      "no-continue": 0,
      "prefer-destructuring": 0,
      "no-plusplus": [
        "error",
        {
          "allowForLoopAfterthoughts": true
        }
      ]
    }
  }
  
- Should be use PureComponent to avoid re-render many times --> https://reactjs.org/docs/react-api.html#reactpurecomponent
- Seperate Container file and Component file --> https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
- Avoid use .bind when handle function --> https://stackoverflow.com/a/32192892/6622971
- Don’t use arrow functions in your render methods --> onPress={(e) => this.handlePress(e)} --> only use when need pass params to handle, or 
  export default ({deleteItem, item}) => {
      const _onDeleteTap(){
          deleteItem(item.id)
      }
      return(
          <TouchableOpacity onPress={_onDeleteTap}>
             <Text>Delete</Text>
          </TouchableOpacity>
  ) }
- Use Redux carefully which avoid re-render many times and avoid use unnecessary. Can use reselect https://github.com/reduxjs/reselect.
- Should be use .eslint to clean code and warning unuse.
- Should be handle "loading" when fetch api do not finish.
- Use Profiler to perf performance when render --> https://www.dropbox.com/s/pt3gwnq4ukzg9xw/Profiler.tar.gz?dl=0
- prettier --write App/**/*.js