Skip to content

Instantly share code, notes, and snippets.

@Pustelto
Last active November 9, 2017 07:43
Show Gist options
  • Save Pustelto/fb4b17c493b9cececa62c9a216cf893c to your computer and use it in GitHub Desktop.
Save Pustelto/fb4b17c493b9cececa62c9a216cf893c to your computer and use it in GitHub Desktop.
Few suggestions for writing more readable and performant code in React native

RN improvement suggestions

Images

When loading image from local storage, don't include size variable manualy. Instead different size variants should be names with @Nx suffix (eg. @2x or @3x) and only suffixless file name should be included. This way RN will pick best image by itself based in device screen.

Bad:

<Image source={require('../../img/graphics/wishlist/checkbox-selected-2x.png')} />

Good:

/**
 * checkbox-selected image assets looks like this in img folder:
 * 
 * checkbox-selected.png
 * checkbox-selected@2x.png
 * checkbox-selected@3x.png
 */
 
<Image source={require('../../img/graphics/wishlist/checkbox-selected.png')} />

Prevent unnecessary re-renders

When ever possible use PureComponent instead of component when creating new react component. PureComponent implements shallowCompare and re-renders only if props are changed. Component doesn't have this optimalization and always re-render. You can use PureComponent in most cases.

Good:

import React from 'react';

class Item extends React.PureComponent {
  // class definition
}

or

import React, { PureComponent } from 'react';

class Item extends PureComponent {
  // class definition
}

Try to avoid passing arrow functions in render method as props to component. This will always reinitialized the function again (during every re-render) and thus the child component will always treat this prop as a new prop and will always re-render. Even if there is no need for it. Same goes if you pass new array or object as a default prop - it always create new array/object and component re-renders.

Bad:

This will always re-render, even if item props didn't change.

<Item
    data={item}
    onClick={() => this.props.clickHandler(item.id)}
/>

Here the default object in data prop will always return new object if item is undefined and cause unnecessary re-renders.

<Item
    data={item || {}}
    onClick={this.clickHandler}
/>

Good:

Pass either a prop and write a click handler as a class method of child component or pass a class method from parent component (depends on the use case).

<Item
    data={item}
    onClick={this.props.clickHandler}
/>

<Item
    data={item}
    onClick={this.clickHandler}
/>

Save default values to constant

const DEFAULT_DATA = {}

<Item
    data={item || DEFAULT_DATA}
    onClick={this.clickHandler}
/>

Better readability

Method binding

Instead of binding class methods in constructor, you can use advanced ES syntax during method declaration. You will need babel transformation for this when writing code for web. For RN, this should work with no additional setup.

Instead of this:

export default class Item extends React.PureComponent {
    constructor(props) {
        super(props);
 
        this.clickHandler = this.clickHandler.bind(this);
        this.showEditMode = this.showEditMode.bind(this);
    }

you can use this:

export default class Item extends React.PureComponent {
    clickHandler = () => {
      // method declaration
    }
    
    showEditMode = () => {
      // method declaration
    }
    
    ...

Destructuring

You can use ES6 destructuring to easily extract properties from object or array

const user = this.props.user
const cart = this.props.cart

is same as:

const { user, cart } = this.props

You can event nest the destructuring if necessary. But in such a case destructured property won't be available.

// Nesting destructuring 
// we have list variable available, but no cart variable
const { cart: { list } } = this.props

// with this we have cart and list variables available in the scope
const { cart, cart: { list } } = this.props

I would suggest to have a look and rest and spread operators in ES6 and array destructuring as well.

Other suggestions

When creating components and their styles try to make them universal and reuseable as much as possible. I saw some styles hook to specific component while it could be in some general style definition.

Same goes for class methods if it should be used on more places, consider moving the method to separate services from where you can later import it. I would consider to do this with API calls (eg. API calls for articles, user...) as some of them are used on more places as well. Function would take only necessary parameters and return result of the call.

I would also suggest to start using using eslint for code consistency, write a tests (at least for services and pure functions used across the app, eg. getItemStatus function is ideal candidate lots of logic there which is hard to debug). Especially later on, when the app will be bigger test can save a lot of time and prevent some regression. Also flowtype to type props of the components and function definitions can be a great help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment