React Native

Learn how to use React Native with deepstream

React Native lets you build mobile apps using only JavaScript. It uses the same design as React, letting you compose a rich mobile UI from declarative components.

Now that deepstream implements websockets, integrating it with your React Native app via the JS connector has become a breeze. The following steps will take you through the process with a hello world-esque example (skip to solution).

Using React Native

1. Start the server

Let’s start by installing the server. Just pick the right version for your operating system and follow its steps. Once the server is installed, you can start it with:

deepstream start

2. Set up the HTML side (optional)

To try some quick tests between the React Native Simulator and a browser window, you can set up an HTML side following the quickstart guide.

3. Initialize and run a new React Native application

First initialize the project in your terminal

react-native init DeepstreamReactNative

Move into the project folder

cd DeepstreamReactNative

Fetch the deepstream code and the url lib it depends on. For usage in react-native the install must include an environment variable in order to run a postinstall script that facilitates integration with react-native. For further explanation see this issue.

DEEPSTREAM_ENV=react-native npm install @deepstream/client --save

Run the app in the iOS simulator (or check the React Native docs for use with the Android simulator)

react-native run-ios

4. React Native Boilerplate

Usually, both the Android and iOS index files are redirected to a central app. To keep things simple for this example, we’ll just alter the index.ios.js file. Note that you should implement this code in index.android.js if you are working with the Android simulator.

Replace the contents of index.ios.js with the following to get a simple text input field in your app:

import React, { Component } from 'react';
import { AppRegistry, TextInput } from 'react-native';

export default class DeepstreamReactNative extends Component {
  constructor(props) {
    super(props);

    const text = '';

    this.state = { text }
  }

  render() {
    const { text } = this.state

    return (
      <TextInput
        style={ {
          height: 40,
          width: 300,
          borderWidth: 2,
          margin: 35,
          padding: 10
        } }
        autoCorrect={false}
        value={text}
        onChangeText={(text) => this.setState({ text })}
      />
    );
  }
}

AppRegistry.registerComponent(
  'DeepstreamReactNative',
  () => DeepstreamReactNative
);

5. Import the deepstream JS component

Since we already installed deepstream in step 3, all we need to do now is import it:

import React, { Component } from 'react';
import { AppRegistry, TextInput } from 'react-native';
import { DeepstreamClient } from '@deepstream/client';

// ...

Then setup the client and record like we saw in the quickstart guide

constructor(props) {
  super(props)

  const client = new DeepstreamClient('localhost:6020')
  client.login()

  const record = client.record.getRecord('some-name')
  // ...

6. Subscribe to changes in our value

Since our text element is already depending on the value of text in our state, we only need to make sure to update that value whenever our record changes:

constructor(props) {
  super(props);

  const client = new DeepstreamClient('localhost:6020')
  client.login()

  const record = client.record.getRecord('some-name')
  const text = ''

  record.subscribe('payload', text => this.setState({ text }));

  // ...

  this.state = { record, text }

7. Push changes from React Native

For the full circle, we will also have to push any change in our text input back to the server. To achieve that, let’s create a method and bind it to the input’s onTextChange:

constructor(props) {

  // ...

  const setRecordFn = (value) => this.state.record.set('payload', value);

  this.state = { record, text, setRecordFn }
render() {
  const { text, setRecordFn } = this.state

  return (
    <TextInput
      // ...
      onChangeText={setRecordFn}
    />
  );

8. Complete!

Your index.ios.js should now look as follows, and the app should work as shown in the animation. Happy developing!

import React, { Component } from 'react';
import { AppRegistry, TextInput } from 'react-native';
import { DeepstreamClient } from '@deepstream/client';

export default class DeepstreamReactNative extends Component {
  constructor(props) {
    super(props);

    const client = new DeepstreamClient('localhost:6020')
    client.login();
    const record = client.record.getRecord('some-name');
    const text = '';

    record.subscribe('payload', (value) => this.setState({ text: value }));

    const setRecordFn = (value) => this.state.record.set('payload', value);

    this.state = { record, text, setRecordFn }
  }

  render() {
    const { text, setRecordFn } = this.state

    return (
      <TextInput
        style={ {
          height: 40,
          width: 300,
          borderWidth: 2,
          margin: 35,
          padding: 10
        } }
        autoCorrect={false}
        value={text}
        onChangeText={setRecordFn}
      />
    );
  }
}

AppRegistry.registerComponent(
  'DeepstreamReactNative',
  () => DeepstreamReactNative
);

9. Building for production

If you are using a minifier for your react-native production build (for example when using expo), make sure to include in the project root the metro bundler config file: metro.config.js with the following values:

module.exports = {
  transformer: {
    minifierConfig: {
      keep_classnames: true,
      keep_fnames: true,
      mangle: {
        keep_classnames: true,
        keep_fnames: true
      }
    }
  }
}