React.jsとFirebaseでツイートアプリを作ってみた 【第1弾】

code

こんにちは。1月に東京のベンチャー企業でエンジニアデビューしました、ひろき(@hiro_az4511)です。

今回は、今の会社で働き始める前に作った、ツイートアプリのコードを紹介していきます。

React.jsとFirebaseで作りましたが、どちらの知識もほぼゼロの状態から1週間ほどで作れました。

はじめてReactとFirebaseを触る方の参考になればと思います。
下記の方に、少しは役に立つかと思います。

こんな方向け記事です
■React.jsを使って何かアプリを作ってみたい。
■Firebaseのデータベースをいじりたい。
■アプリをFirebaseでデプロイさせたい。

本記事は第一弾。

create-react-appを用いて、簡単なツイートアプリを作るところまでをやっていきます。

React.jsの基礎を学ぶには

実際に私がReact.jsの学習に使った教材は、下記記事で詳しく紹介しています。

仮想DOMやState、Propsなどの概念を理解した上で進めていただければと思います。

そんなもんいいからとりあえず作ってみたい!っという方は次に進んでくださいw

create-react-appでReactアプリ作成

create-react-appコマンドを使うためには、Node.js 8.10.0以上がインストールが必須のようです。(参照

Node.jsは簡単に言うと、サーバーサイドJavaScriptの実行環境です。

下記のようにバージョンを確認してください。もしない方はこちらからインストールしましょう。

$ node -v

v10.14.2

npm v

6.4.1

また、Node.jsをインストールするとnpm(Node Package Manager)という、Node.jsのモジュールを管理するツールが使えるようになります。上のように、バージョンを確認してみると、しっかりバージョンが表示されるかと思います。

ここでは、高速でパッケージをインストールできると言われている、JavaScriptパッケージマネジャーのYarnを使ってアプリを作っていきます。

まずは、npmでyarnをインストールします

$npm install -g yarn

次に、create-react-appをインストールし、projectsというディレクトリにアプリを作ってみましょう。(参考

$ yarn global add create-react-app

$ create-react-app ~/projects/react-firebase-chat-app

Happy hacking!という言葉が出てくれば、成功です!

実際にアプリを起動してみます。

$ cd /projects/react-firebase-chat-app

$ yarn start

下記のような画面が出てくればしっかりアプリが作れてます!

公式ドキュメントのTo Doアプリを改造

今回のchatアプリは、React公式ドキュメントに記載されているTODOアプリをもとに作りました。

今回のアプリでは初期状態でindex.jsから呼ばれている、src/App.jsを書き換えていきます。

細かいファイル構成等についてはここでは触れません。

基本的な構造

このアプリはメインであるAppコンポーネントと、ツイートを表示するエリアのTweet Listコンポーネントの2つの構成になっています。

App.jsコード

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { items: [], user: '', text: '' };
    this.tweet = this.tweet.bind(this);
    this.userName = this.userName.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  render() {
    return (
      <React.Fragment>
        <header>つぶやきアプリ</header>
        <div className="container">
          <form onSubmit={this.handleSubmit}
                autoComplete="off">
            <input
              onChange={this.userName}
              value={this.state.user}
              id='tweets'
              placeholder="あなたの名前"
            /><br/>
            <textarea
              id="new-todo"
              onChange={this.tweet}
              value={this.state.text}
              placeholder="今何してる?"
            /><br/>
            <button
              className="btn btn-success"
              type="submit"
            >つぶやく
            </button>
          </form>
          </div>
       {/*  TweetList Componentの呼び出し */}
        <div className="tweet-list">
          <TweetList items={this.state.items} />
        </div>
      </React.Fragment>
    );
  }

  tweet(event) {
    this.setState({ text: event.target.value });
  }

  userName(event){
    this.setState({ user: event.target.value});
  }

  handleSubmit(event) {
    {/*  ユーザー名・ツイートが入力されなかった場合のバリデーション */}
    event.preventDefault();
    if(this.state.user === "") {
      alert('ユーザー名を入力してください')
      return;
    } else if(this.state.text === "") {
      alert('ツイート内容を入力してください')
      return;
    }

    const newItem = {
      user: this.state.user,
      text: this.state.text,
    };

    this.setState(state => ({
      items: state.items.concat(newItem),
      user: '',
      text: ''
    }));
  }
}

class TweetList extends React.Component {
  render() {
    return (
      <React.Fragment>
        <ul>
          {this.props.items.map((item, i) => (
            <li key={i}>
            <div className="line-bc">
              <div className="balloon6">
                <div className="faceicon">
                  <img src="favicon.ico"/>
                    {item.user}
                </div>
                <div className="chatting">
                  <div className="says">
                    <p>{item.text}</p>
                  </div>
                </div>
              </div>
            </div>
            </li>
          ))}
        </ul>
      </React.Fragment>
    );
  }
}

export default App;

特に難しいことはしていませんが、公式ドキュメントのTODOアプリと変わる点としては、入力箇所が2つに増えた点と、入力されないで「つぶやく」ボタンが押された時に、「〇〇を入力してください」というAlertを出して簡単なバリデーションを付けた点です。

上記のコードと、公式ドキュメントを見比べてみてください。

App.css

それっぽいデザインにするために、こちらのサイトを参考に、下記のようにCSSを書きました。

/*ツイートリスト*/
.tweet-list{
  width:350px;
  margin-left: auto;
  margin-right: auto;
  border-radius: 10px;
  background: #5ED3CF;
}

/*line風のUI*/
.line-bc {
  padding: 5px 10px;
  max-width: 450px;
  text-align: right;
  font-size: 14px;
  background: #5ED3CF;
  border-radius: 10px;
  word-wrap: break-word;
}

/*吹き出し部分*/
.balloon6 {
    width: 100%;
    margin: 10px 0;
    overflow: hidden;
}

.balloon6 .faceicon {
    float: left;
    margin-right: -50px;
    width: 60px;
    text-align: center;
}

.balloon6 .faceicon img{
    width: 100%;
    height: auto;
    border-radius: 50%;
}
.balloon6 .chatting {
    width: 100%;
    text-align: left;
}
.says {
    display: inline-block;
    position: relative;
    margin: 20px 0 0 70px;
    padding: 10px;
    max-width: 230px;
    border-radius: 12px;
    background: #edf1ee;
}

.says:after {
    content: "";
    display: inline-block;
    position: absolute;
    top: 3px;
    left: -19px;
    border: 8px solid transparent;
    border-right: 18px solid #edf1ee;
    -ms-transform: rotate(35deg);
    -webkit-transform: rotate(35deg);
    transform: rotate(35deg);
}
.says p {
    margin: 0;
    padding: 0;
}

まとめ

いかがでしたでしょうか。

下記のようなアプリができましたか?

「なぜ、こんな書き方しているの?」

「こっちのほうがいいんじゃない?」

というようなご意見がございましたらコメントいただけると嬉しいです。

次の記事では、FirebaseのCloud Firestoreを使って、このアプリのツイートをデータベースに入れる+データベースから読み込む作業をしていきます。

それでは!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です