Socket.ioとReactNaiveの連携(の概要)


Socket.ioとReactNativeの接続をテストしてみます(本当の触りだけです)。
Socketのサーバ側は特に重要ではないのでGet Startedのコードを流用させていただきます。

Socket Serverの準備

準備

まずは作業ディレクトリを作成し、必要なモジュールをインストールしておきます。

mkdir socket-server
cd socket-server
npm init -y

npm install --save express socket.io

index.js

Socketサーバを実装します。
今回は、全員配信に加え、個人配信も試します。

  • io.emit()で全員配信
  • io.to(id).emit()で個人配信(正確にはroom配信)
index.js
var express = require('express');
var app = express();
var http = require('http').Server(app);
const io = require('socket.io')(http);

app.get('/', function (req, res) {
    res.sendFile(__dirname + '/index.html');
});

io.on('connection',function(socket){
    socket.on('message',function(msg){

        console.log('message: ' + msg);

        //全員に配信
        io.emit('message', msg);

        //特定のIDに配信(ここでは送ってきたIDに返信)
        io.to(socket.id).emit('personal', 'PERSONAL');
        console.log('id: ' + socket.id)
    });
});

http.listen(3000, function () {
    console.log('server start @3000 port');
});

ここで重要なことはHTML自体はSocketサーバの動きとは全く関係ないことです。サーバは http://localhost:3000 としてルーティングの指定に関係なく起動します。

index.html

Webは本来関係ありませんが、動作確認用に用意します。

index.html
<!DOCTYPE html>
<html>

<head>
    <title>socket test</title>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
</head>

<body>
    <ul id="messages"></ul>
    <form id="message_form" action="#">
        <input id="input_msg" autocomplete="off" /><button>Send</button>
    </form>
    <script>
        $(function () {

            var socketio = io();

            //内容を送る
            $('#message_form').submit(function () {
                socketio.emit('message', $('#input_msg').val());
                $('#input_msg').val('');
                return false;
            });

            //全員配信を受け取る
            socketio.on('message', function (msg) {
                $('#messages').append($('<li>').text(msg));
            });

            //個人配信を受け取る
            socketio.on('personal', function(msg){
                console.log(msg);
            })

        });
    </script>
</body>

</html>

動作確認

動作確認してみます。まず、サーバを起動させます。

node index.js

全員配信用のコンテンツは全ブラウザに反映され、投稿者(左)のみ、PERSONALと表示されています。
サーバ自体は正しく動作しているようです。

ReactNativeから利用してみる

では本題のReactNativeからの利用です。
socket.io-clientというモジュールを利用することで連携できるようです。

expo init socket-client
cd socket-client

npm install --save socket.io-client
npm install

App.js

では、簡単なコードをApp.jsに記述してみます。
ボタンを押したらemitする機能と全員および個人配信を受け取ります。今回は描画はせずconsole.log()で出力するだけです。

App.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import io from 'socket.io-client';

const socket = io('http://localhost:3000', {transports: ['websocket']} );

export default class App extends React.Component {
  render() {

    //全員配信の受け取り
    socket.on('message', function(msg){
      console.log(msg);
    })

    //個人配信の受け取り
    socket.on('personal', function(msg){
      console.log(msg);
    })

    return (
      <View style={styles.container}>
        <Text>Open up App.js to start working on your app!</Text>
        {/* メッセージ送信 */}
        <Button
          title="emit"
          onPress={() => socket.emit('message','from React')}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

動作確認

Reactアプリのボタンを押すとfrom Reactが投稿され、かつPERSONALが戻ってきています。

Webにも反映されています。

簡単ですが、以上です。