LoginSignup
71
80

More than 5 years have passed since last update.

1時間でリアルタイムチャットを作る(React + FireBase + Material UI)

Last updated at Posted at 2018-02-27

React + Firebase + Material UIを用いて短時間でリアルタイムチャットを開発する手順をまとめました。短時間でのサンプル開発のため、今回はシンプルに投稿ができる要素のみになります。

完成サンプル:
スクリーンショット 2018-02-28 4.12.10.png

準備

node.js、npmのインストール

brew install nodebrew
mkdir -p ~/.nodebrew/src
nodebrew install-binary latest

# 最新バージョンを確認(今回はv9.5.0であることを確認)
nodebrew list

# nodejsを有効にする
nodebrew v9.5.0

# コマンドのパスを通す
echo 'export PATH=$PATH:/Users/ユーザ名/.nodebrew/current/bin' >> ~/.bashrc

# bash_profileをtouch
touch .bash_profile

~/.bashrc

if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
source ~/.bashrc

# npm、nodeコマンドがたたけるかを確認
node -v
npm -v

IDEの用意

今回は、Atomを使用する事にしました。

参考)
Atom : https://atom.io/
Webstrom : https://www.jetbrains.com/webstorm/

React

Reactプロジェクト作成

参考)
https://reactjs.org/tutorial/tutorial.html


mkdir {指定ディレクトリ}
cd {指定ディレクトリ}

# React tutorialプロジェクトを作成
npm install -g create-react-app
create-react-app tutorial

テスト実行

# http:://localhost:3000/に環境ができていることを確認
npm start

FireBase

コンソールを開き、プロジェクトを作成

https://console.firebase.google.com/u/0/?hl=ja
※無料版は、プロジェクト数が5つまでと制限されているが、申請すれば上限を無料で増やしてくれるらしい。

スクリーンショット 2018-02-28 2.49.24.png

Firebaseの設定

作成したプロジェクトを開き、Authenticationページへ
スクリーンショット 2018-02-28 2.50.29.png

右上にある「ウェブ設定」をクリックし、設定情報をコピーします。
これらの値が今回使用するFirebase設定情報になります。

tutorialプロジェクト内に戻り、src/firebase/config.jsを用意し、上記で取得した設定情報を入力し保存します。
以下の文献もとても参考になりました。
https://qiita.com/kazushikawamura/items/58ea222b3cc289882d79

src/config/config.js
export const firebaseConfig = {
  apiKey: "***************",
  authDomain: "***************",
  databaseURL: "https://***************",
  projectId: "***************",
  storageBucket: "***************",
  messagingSenderId: "***************"
};

src/firebase/index.jsを用意し、Firebase Databaseを使用するための初期化処理を行う設定を書きます。

src/config/index.js
import firebase from 'firebase';
import { firebaseConfig } from './config.js';

export const firebaseApp = firebase.initializeApp(firebaseConfig);
export const firebaseDb = firebaseApp.database();

Firebaseへデプロイ

npm install -g firebase-tools
firebase init
firebase login

firebase.jsonを以下のように設定します。

firebase.json
{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "build"
  }
}

database.rules.jsonを以下のように設定します。

database.rules.json
{
  "rules": {
    ".read": "true",
    ".write": "true"
  }
}

Firebase Databaseへのデプロイを実行します。

npm run build
firebase deploy

Material UI

Material UIのインストール

参考)
https://www.npmjs.com/package/material-ui

npm install material-ui

cssを用意する

Reactプロジェクト内の構造を整理するため、今回はデフォルトで用意されているApp.cssなどをsrc/cssに移動しました。
中身については、Material UIを用いるので特にデフォルトのままで利用します。

Componentを作成

再び参考)
https://qiita.com/kazushikawamura/items/58ea222b3cc289882d79

src/components/ChatBox.jsを作成。

チャットの投稿フォームのUIが実装されています。
Materila UIのパーツを利用するには、MuiThemeProviderをimportし、
タグで囲うことで、その中で各種コンポーネントを使用することが出来ます。
http://www.material-ui.com/#/get-started/usage

Material UIのRaisedButton、TextFieldパーツを用いています。
http://www.material-ui.com/#/components/raised-button
http://www.material-ui.com/#/components/text-field

src/components/ChatBox.js
import React from "react";
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';

export default class ChatBox extends React.Component {
  render() {
    return (
      <MuiThemeProvider>
        <div className="ChatBox">
          <div className="">
            <TextField name='user_name' onChange={this.props.onTextChange} className=""  placeholder="Name" />
<br />
            <TextField name='profile_image' onChange={this.props.onTextChange} className="" placeholder="Profile Image URL" />
          </div>
          <TextField rows="4" multiLine="true" name='text' className="" onChange={this.props.onTextChange} />
          <RaisedButton primary="true" label="Send" className="" onClick={this.props.onButtonClick} />
        </div>
      </MuiThemeProvider>
    );
  }
}

src/components/Message.jsを作成。

投稿されたチャット内容のUIを実装します。

Material UIのAvatar、List、ListItem、Chipパーツを用いています。
http://www.material-ui.com/#/components/avatar
http://www.material-ui.com/#/components/list
http://www.material-ui.com/#/components/chip

src/components/Message.js
import React from "react";
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Avatar from 'material-ui/Avatar';
import List from 'material-ui/List/List';
import ListItem from 'material-ui/List/ListItem';
import Chip from 'material-ui/Chip';

const styles = {
  chip: {
    margin: 4,
  },
  wrapper: {
    display: 'flex',
    flexWrap: 'wrap',
  },
};

const style = {margintop: -5};

export default class Message extends React.Component {
  render() {
    return (
      <div className="Message">
      <List>
        <ListItem disabled="true">
          <Avatar className="" src={this.props.message.profile_image} />
          <span style={{marginBottom: -5}}>@{this.props.message.user_name}</span>
          <div className="">
            <Chip style={styles.chip} >
              {this.props.message.text}
            </Chip>
          </div>
        </ListItem>
      </List>
      </div>
    );
  }
}

src/components/AppChat.jsを作成。

チャット全体のUIを構成します。
上記で用意したChatBox、Messageを用います。
また、onTextChange()、onButtonClick()を用意して、各種アクションを実装します。

src/components/AppChat.js
import React, { Component } from 'react';
import './../css/App.css';
import { firebaseDb } from './../firebase/index.js'
import Message from './Message.js'
import ChatBox from './ChatBox.js'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

const messagesRef = firebaseDb.ref('messages')

class AppChat extends Component {
  constructor(props) {
    super(props);
    this.onTextChange = this.onTextChange.bind(this)
    this.onButtonClick = this.onButtonClick.bind(this)
    this.state = {
      text : "",
      user_name: "",
      profile_image: "",
      messages : []
    }
  }

  render() {
    return (
      <MuiThemeProvider>
        <div className="App">
          <div className="App-header">
            <h2>Chat</h2>
          </div>
          <div className="MessageList">
            {this.state.messages.map((m, i) => {
              return <Message key={i} message={m} />
            })}
          </div>
          <ChatBox onTextChange={this.onTextChange} onButtonClick={this.onButtonClick} />
        </div>
      </MuiThemeProvider>
    );
  }

  onTextChange(e) {
    if(e.target.name == 'user_name') {
      this.setState({
        "user_name": e.target.value,
      });
    } else if (e.target.name == 'profile_image') {
      this.setState({
        "profile_image": e.target.value,
      });
    } else if (e.target.name == 'text') {
      this.setState({
        "text": e.target.value,
      });
    }
  }

  onButtonClick() {
    if(this.state.user_name == "") {
      alert('user_name empty')
      return
    } else if(this.state.text == "") {
      alert('text empty')
      return
    }
    messagesRef.push({
      "user_name" : this.state.user_name,
      "profile_image" : this.state.profile_image,
      "text" : this.state.text,
    })
  }

  componentWillMount() {
    messagesRef.on('child_added', (snapshot) => {
      const m = snapshot.val()
      let msgs = this.state.messages

      msgs.push({
        'text' : m.text,
        'user_name' : m.user_name,
        'profile_image' : m.profile_image,
      })

      this.setState({
        messages : msgs
      });
    })
  }

}

export default AppChat;

src/index.jsを編集し、上記AppChat.jsを呼び出すようにする

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './css/index.css';
import registerServiceWorker from './registerServiceWorker';
import AppChat from './components/AppChat';
import injectTapEventPlugin from 'react-tap-event-plugin';

ReactDOM.render(<AppChat />, document.getElementById('root'));
registerServiceWorker();

 チャットアプリを実行

npm start

感想・まとめ

  • Reactを今回はじめて触れていきましたが、これまでのHTML、jsの書き方とは若干異なるためコーディングを覚えていく必要があると感じた。
  • 今回は特に触れていないが、Reduxを用いるものになってくるとより複雑な状態遷移のアプリケーションも開発することができるとのことなので、今後触れていきたい。
  • Firebaseは、思惑通りリアルタイムチャットを用意に実現してくれたので本件については非常に満足したが、細かい用途に対してどこまでカスタマイズしていけるかは引き続き要調査。
  • Material UIは、bootstrapのようなシンプルでスッキリしたUIを簡単に用意することができる。また、カスタマイズに関しても柔軟なようなので今後もReactプロジェクトでは活用していきたい。
  • 今回のチャットサンプルの実装でも、他Qiita文献には大変お世話になりました。感謝。
  • 実際1時間で作れたかと言うと、間に別件対応なども入ってしまったため、実際には3時間程度かかってしまいました。それらがなくストレートにいければ、この手順を見ながら1時間以内で作っていけるかと思います。
71
80
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71
80