React Native

for

The world

Alfian Busyro (Aru)

Ex Nano Team

(June 2017-October 2017)

Agenda

  • React Native Under the hood
  • Rendering the right way
  • Code usability
  • Misc
  • The future of RN

React Native Under the Hood

RN Under the Hood

Thread

RN Under the Hood

Rendering update

RN Under the Hood

Rendering update

RN Under the Hood

Technologies behind the layer

Yoga

Internal
MessageQueue

import MessageQueue from 'react-native/Libraries/Utilities/MessageQueue'
MessageQueue.spy((info)=>console.log("event!", info))

RN Under the Hood

React Lifecycle

Rendering

the right way

Limiting re-Render

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState) {
  return (
    (!isEqual(this.props.a, nextProps.a)) ||
    (!isEqual(this.state.data, nextState.data))
  )
}

Limiting re-Render

PureComponent  FTW!

// From

export default class AwesomeComponent extends React.Component {

// To

export default class AwesomeComponent extends React.PureComponent {
  • Pass all data to PureComponent props
  • Complex state or props data
  • inline object data ( since {} !== {} )

Limiting re-Render

 Use key attribute on list items

class MyComponent extends React.PureComponent {
  render() {
    return this.props.data.map((item, i) => {
      return <Text key={item.id}>{item.title}</Text>
    });
  }
}

Prevent Rendering Blocking

export default class AwesomeComponent extends Component {

  glamorousAsyncProcess() {
    // redux action that remains forever
  }

  constructor() {
    super()
    // don't
    glamorousAsyncProcess()
  }

  componentWillMount() {
    // don't
    glamorousAsyncProcess()
  }

  async populateUser() {
    // populate 1M Users
    await this.props.populateMillionUsers()
  }

  render() {
    //don't
    populateUser()
    
    return(
      <View>
        <Text>
          Hello World! with heavy process on the back
        </Text>
      </View>
    )
  }

}

Prevent Rendering Blocking

class AwesomeComponent extends Component {

  glamorousAsyncProcess() {
    // redux action that remains forever
  }

  constructor() {
    super()
    this.viewContacts = this.viewContacts.bind(this)
  }

  componentDidMount() {
    // do
    glamorousAsyncProcess()
  }

  viewContacts() {
    // Show Contact List
  }

  render() {
    
    return(
      <View>
        <Text>
          Hello World! with heavy process on the back
        </Text>
        <TouchableOpacity onPress={this.viewContacts} >
          <Text>Press Me!</Text>
        </TouchableOpacity>
      </View>
    )
  }
}

List & Scroll

FlatList & SectionList > ListView & ScrollView

Advantages:

  • PureComponent
  • Only render visible view
  • Pull to refresh
  • Section header (Section List)

Common issue:

  • multiple onPress function
  • pass big data to renderItem Component props

 

Deferred heavy process

import nextFrame from 'next-frame';

// ...

for (let recording of recordingsJSON) {
  await nextFrame(); // This is all we need to add!
  mergeRecordingToLocalDatabase(recording);
}

https://github.com/corbt/next-frame

https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

Deferred heavy process

Double defenses

let setDefaultAddressInRedux = async () => {
  await nextFrame()
  setTimeout(() => {
    self.props.setDefaultAddressInRedux(selectedDefaultAddress)
  }, 0)
}
setDefaultAddressInRedux()

Code Usability

Keep it DRY

How to create Component

Constant

// Avoid these

let hitam = 'hitam pekat'
// di lain tempat
let hitam = 'hitam cerah'

let tambah = (a, b) => a +b
// di lain tempat
let tambah = (a) => a + 1

Miscellaneous

Redux

Redux

You Might Not Need Redux 

-Dan Abramov

Redux

Redux hanya diperlukan untuk state yang dibutuhkan oleh beberapa Component yang berbeda 

- Alfian

Redux Alternatives

Context API

import React, {Component } from 'react'
import createReactContext from 'create-react-context'
import { getPhotos } from '../Services/Apis/Search'

const SearcContext =  createReactContext({
  data: null
})

export const SearchConsumer = SearcContext.Consumer

export class SearchProvider extends Component {
  state = {
    data: null,
    isFetching: false,
    error: false
  }

  request = async (tag) => {
    this.setState({
      isFetching: true
    })
    let data = await getPhotos(tag)
    let arrayPost = data.posts.map((obj, i) => {
      obj.key = i
      return obj
    })
    this.setState({
      data: arrayPost,
      error: false,
      isFetching: false
    })
  }

  render() {

    const { data, isFetching, error } = this.state

    return(
      <SearcContext.Provider
        value={{
          data: data,
          isFetching: isFetching,
          error: error,
          request: this.request
        }}
      >
        {this.props.children}
      </SearcContext.Provider>
    )
  }  
}

Async Storage

 is a simple, unencrypted, asynchronous, persistent, key-value storage system that is global to the app

AsyncStorage Alternatives

Accessibility

Accessibility

accessible={true}
accessibilityLabel="You can hear me via VoiceOver"

AccessibilityTraits / AccessibilityRole

  • Button
  • link
  • search
  • image

move files around until it feels right

http://react-file-structure.surge.sh/

The future

of

React Native

Airbnb

drop

React Native

Fabric

Fabric Architecture

Fabric summaries

  • Shadow thread run on any threads ( no shadow tree, synchronous ftw! )
  • Immutable Shadow tree (thread safe)
  • new Javascript VM interface (Free to use any JSC, even V8)
  • Shadow tree will be written on C++

Thank you

Inquiries :

React NativeforThe world

By Alfian Busyro

React NativeforThe world

  • 600