Hyphenate Docs

Start Chatting with Hyphenate!

Welcome to the Hyphenate docs portal. Here you'll find comprehensive guides and technical documentation to help you integrate Hyphenate In-App Chat.

Get Started

The ultimate guide for building a React Native mobile app with in-app chat

What’s React Native?

In short, React Native is mobile app development methodology heavily invested in by Facebook, which allows developers to build native iOS and Android in JavaScript that's inspired by React. React Native is like React, but it uses native components as building blocks instead of web components. As a result, React Native is not a hybrid app (PhoneGap, Cordova, or Ionic), because it is essentially a wrapper framework on top of the same fundamental UI building blocks as regular iOS and Android apps, instead of “mobile web app” an “HTML5 app” that use web components. The goal of React Native is to build a high performance mobile app that's indistinguishable from the ones that are built using Objective-C/Swift or Java, but without sacrificing the resources by building two completely separate apps. Learn more about React Native

React framework - the main objective of React is to solve the problem of rendering UI components efficiently by removing both asynchrony and direct DOM manipulation.

Getting Started

Pre-Requisites

Install React Native

Here's an extraction of the React Native full and detailed installation guide

$ npm init
$ npm install --save react react-dom
  • Package manager, such as Yarn or npm. It handles third-party package dependency, as well as enables the ability to easily install or update them.
  • Bundler, such as webpack or Browserify. It lets you write modular code and bundles it into small packages to optimize load time.
  • Compiler such as Babel. It lets you write modern JavaScript code that still works in older browsers.

Install Hyphenate Messaging Library

  1. Sign up a developer account for Hyphenate Mobile Instant Messaging platform. Hyphenate developer console

  2. Download Hyphenate React Native Demo and SDK

  3. React Native SDK lives in /App/Sdk. While it's still in the process of migrating to npm, please manually place that folder in your React Native app project from the Hyphenate demo project.

  4. In order to initiate the Hyphenate messaging features, you need to implement the logic under two files to your app, WebIM.js and WebIMConfig.js, under React Native demo app /App/Lib.

WebIMConfig.js

Replace the API key appkey in WebIMConfig.js with the one you obtained from the Hyphenate developer console

let config = {
  ...
  /*
   * Application API Key
   */
    appkey: 'hyphenatedemo#hyphenatedemo',
  ...
};

WebIM.js

You can also see we use modified Strophe, an XMPP library for JavaScript, in order to adapt React Native applications.

// import strophe library
import Strophe from 'strophe';
// Hyphenate SDK config
import webConfig from './WebIMConfig'
// Hyphenate SDK
import websdk from '../Sdk'

// solve the dependency of strophe to DOMParser
window.DOMParser = require('xmldom').DOMParser;
// solve the dependency of strophe to document
window.document = new DOMParser().parseFromString("<?xml version='1.0'?>", 'text/xml');

let WebIM = window.WebIM = websdk;
window.WebIM.config = webConfig;

...

Package Dependencies

Add the packages you desire to package.json to let npm handle the package dependencies, installation, and updates automatically.

package.json

...
"dependencies": {
  "react": "^15.4.1",
  "react-native": "^0.39.2",

  "redux": "^3.6.0",
},
...

In-app Messaging Under the Hood

In this demo app, we use the altered version of Hyphenate web SDK due to the structural differences between React Native and web applications. SDK is building on top of XMPP library, Strophe, with custom layer websdk.browser.js to bridge the functions.

Hyphenate Web and React Native SDKs are using different protocols from mobile SDKs for iOS and Android. Instead of XMPP, mobile SDKs are based on protocol MSYNC developed by Hyphenate. All SDKs by Hyphenate can communicate with other platforms seamlessly. In short, it is based on binary format instead of raw text like XML, which is able to compress message data up to 80%. MSYNC also reduces the message relay between client and server. As a result, MSYNC is able to deliver more information with significantly less overhead, less network bandwidth consumption, and better battery preservation.

Hyphenate React Native SDK

Hyphenate React Native SDK functions live under /App/Sdk/src.

  • connection.js handles all the messaging features
  • emoji.js modify this file to enrich your custom emoji collection
  • message.js different message bodies: text, command, location, audio, image, file, video
  • queue.js message queue
  • status.js statues of connection, message, etc
  • utils.js miscellaneous functions

SDK Configuration for Your App

As mentioned earlier in the Install Hyphenate Messaging Library section, you need to configure the logic from files, WebIM.js and WebIMConfig.js, under the React Native demo app /App/Lib to initiate the messaging features.

Let's send a one-to-one message in text

sendTxtMessage function

The function, sendTxtMessage, to send the text message is defined in MessageRedux.js in /App/Redux, which also contains the function sendImgMessage.

const {Types, Creators} = createActions({

  addMessage: ['message', 'bodyType'],
  updateMessageStatus: ['message', 'status'],

  // ---------------async------------------
  sendTxtMessage: (chatType, chatId, message = {}) => {
    return (dispatch, getState) => {
      const pMessage = parseFromLocal(chatType, chatId, message, 'txt')
      const {body, id, to} = pMessage
      const {type, msg} = body
      const msgObj = new WebIM.message(type, id);
      console.log(pMessage)

      msgObj.set({
        msg, to, roomType: false,
        success: function () {
          dispatch(Creators.updateMessageStatus(pMessage, 'sent'))
        },
        fail: function () {
          dispatch(Creators.updateMessageStatus(pMessage, 'fail'))
        }
      });

      // TODO: update group chat logic
      // if (type !== 'chat') {
      //   msgObj.setGroup('groupchat');
      // }

      WebIM.conn.send(msgObj.body);
      dispatch(Creators.addMessage(pMessage, type))
    }
  }
)};

Send message

You can find an example of sending text messages in the demo app /App/Containers/MessageScreen.js.

Render text input view

_renderMessageBar() {
        const {value = '', isEmoji} = this.state;

        return (
            <View style={Styles.search}>
              <View style={Styles.inputRow}>
                <View style={Styles.searchRow}>
                  <TextInput
                      ref="search"
                      style={[Styles.searchInput, {height: Math.min(Math.max(this.state.height, 34), 100)}]}
                      value={value}
                      editable={true}
                      keyboardType='default'
                      returnKeyType='default'
                      autoCapitalize='none'
                      autoCorrect={false}
                      multiline={true}
                      onChange={(event) => {
                          this.setState({
                              value: event.nativeEvent.text,
                              // 5 for padding
                              height: event.nativeEvent.contentSize.height + 5,
                          });
                      }}
                      onFocus={this.handleFocusSearch.bind(this)}
                      onBlur={this.handleBlurSearch.bind(this)}
                      onChangeText={this.handleChangeText.bind(this)}
                      onEndEditing={() => {
                      }}
                      onLayout={() => {
                      }}
                      underlineColorAndroid='transparent'
                      onSubmitEditing={() => this.refs.search.focus()}
                      // I18n for Internationalization
                      placeholder={I18n.t('sendMessage')}
                  />
                </View>
                  {this._renderSendButton()}
              </View>
                {/*// emoji is sending in text format with emoji library mapping*/}
                {this._renderEmoji()}
            </View>
        )
    }

Send button triggered

// send button tapped
_renderSendButton() {
    const {focused} = this.state

    return focused ? (
            <TouchableOpacity style={Styles.searchExtra} onPress={this.handleSend.bind(this)}>
              <Text style={Styles.sendText}>{I18n.t('send')}</Text>
            </TouchableOpacity>
        ) : null
}

// handle message sending
handleSend() {
    // input text message to be sent is this.state.value
    if (!this.state.value || !this.state.value.trim()) return;
    this.props.sendTxtMessage(this.props.chatType, this.props.id, {
        msg: this.state.value.trim()
    });
    this.setState({
        value: '',
        height: 34
    })
}

Link to Redux functions

import React, {Component, PropTypes} from 'react'

MessageScreen.propTypes = {
    message: PropTypes.object,
    // chatType: PropTypes.oneOf(['chat', 'groupChat']),
    // id: PropTypes.string
};

const mapStateToProps = (state) => {
    return {
        message: state.entities.message,
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        sendTxtMessage: (chatType, id, message) => dispatch(MessageActions.sendTxtMessage(chatType, id, message)),
        sendImgMessage: (chatType, id, message, source) => dispatch(MessageActions.sendImgMessage(chatType, id, message, source))
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(MessageScreen)

State Management

Redux vs. Flux

First, what are they? Both are open source application architectures for building client-side web applications by providing a new alternative approach to the traditional MVC problems. Flux is developed by Facebook and Redux is a popular alternative derived from Flux. They are very similar in terms of state management approaches.

Both do,

  • The unidirectional data flow reduces the complexity of state dependencies that we often see in model-view-controller model.
  • State is read-only The only way to change the state is to emit an action, an object describing what happened.
  • model update logic “Stores” in Flux and “reducers” in Redux that ties state and actions together; a function takes previous state and action as arguments, and returns the next state. see example.

but Redux has some advantages over Flux,

  • Single source Redux has only single source, the state of your whole application is stored in an object tree within a single store.
  • Pure functions Redux does not have the concept of a Dispatcher. This is because it relies on pure functions instead of event emitters, and pure functions are easy to compose and don't need an additional entity managing them. Depending on how you view Flux, you may see this as either a deviation or an implementation detail. Flux has often been described as (state, action) => state. In this sense, Redux is true to the Flux architecture, but makes it simpler thanks to pure functions.
  • Data integrity Redux assumes you never mutate your data. You can use plain objects and arrays for your state just fine, but mutating them inside the reducers is strongly discouraged. You should always return a new object, which is easy with the object spread operator proposal, or with a library like Immutable.
  • Plus, even Facebook F8 open source apps use Redux. See tutorial

Sources

Some Useful Packages

Add the packages you desire to package.json to let npm handle the package dependencies, installation, and updates automatically

package.json

"dependencies": {
  "express": "~4.14.0",
  "querystringify": "0.0.4"
},
"devDependencies": {
  "eslint": "~3.8.1",
},

Flow

A static type checker for JavaScript that helps you catch common bugs. flowtype.org

Reactotron

An OS X app for inspecting your React JS and React Native apps. check it out

and More!

JS.Coach has a list of popular packages for React Native.

Resources

The ultimate guide for building a React Native mobile app with in-app chat


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.