ReactとFirebaseで一から地道にチャット掲示板を作っていく

ReactとFirebaseで一から地道にチャット掲示板を作っていく:

Reactビギナーがウェブサービスを作っていく過程を公開していこうと思います。

アイディアとしては、リアルタイムチャットが出来る掲示板を目指していこうかと考えています。

今回は、Reactのセットアップと以下の様な簡易的なチャット機能を作ろうと思います。



apicallerrorgif.gif


開発中のレポジトリはこちらになります https://github.com/ychino/craigschat

最新の動いているアプリはこちらです https://craigschat-230e6.firebaseapp.com/


Reactアプリケーションの作成

まずはcreate-react-appをローカルにインストールします。

npm install -g create-react-app 
お好きなディレクトリに移動し、Reactプロジェクトを作成します。現時点ではcraigslistのような掲示板でさらにslackのようなチャット機能を持ち合わせたものを構想しているので、craigschatという名前でいきたいと思います。

create-react-app cragschat  
cd craigschat 
npm start 
そして、http://localhost:3000/ にアクセスすると、、、タラーン!いいですね。無事動いているようです。



Capture1.PNG



チャット機能を作っていく

まずは、チャットに必要なコメントを入力するボックスを作っていきたいと思います。

現時点で以下の様な構成となっています。src配下にcomponentsフォルダを作成し、その下にCommentBox.jsを作成しました。



Capture2.PNG


// CommentBox.js 
 
import React from 'react'; 
 
export const CommentBox = (props) => ( 
  <div> 
    <input 
      name='userName' 
      placeholder='username' 
    /> 
   <textarea 
      name='text' 
      placeholder="comment" 
    /> 
    <button>Comment</button> 
  </div> 
) 
そして、このコメントボックスコンポーネントをインポートし、表示するためApp.jsを以下の様に変更します。

// App.js 
 
import React, { Component } from 'react'; 
import { CommentBox } from './components/CommentBox' 
import './App.css'; 
 
class App extends Component { 
  render() { 
    return ( 
      <div className="App"> 
       <h1>Chat</h1> 
       <CommentBox /> 
      </div> 
    ); 
  } 
} 
 
export default App; 
 
いい感じです。コメントボックスが表示されました。



Capture3.PNG


続いて、コメントの投稿機能を作って行きたいと思います。とりあえず、App.jsのstateとしてコメントを保存していきたいと思いますので、App.jsを以下の様に変更します。

ここで行っていることは、App.jsにuserName及びtextを保存する為のstateを設定し、CommentBox.jsのフォームから渡される値をstateへ保存するためのonTextChangeメソッドを設定しています。

this.onTextChange = this.onTextChange.bind(this);を忘れずに。bind(this)って何?って方はこちらをご参照ください(https://reactjs.org/docs/handling-events.html) 。


最後にrenderメソッド内でCommentBoxコンポーネントにtext/userName state及びonTextChangeメソッドをpropsとして渡します。

// App.js 
 
import React, { Component } from 'react'; 
import { CommentBox } from './components/CommentBox' 
import './App.css'; 
 
class App extends Component { 
  constructor(props) { 
    super(props); 
 
    this.state = { 
      userName: "", 
      text : "", 
    } 
 
    this.onTextChange = this.onTextChange.bind(this); 
  } 
 
  onTextChange(e) { 
    if(e.target.name === 'userName') { 
      this.setState({ 
        userName : e.target.value, 
      }); 
    } else if (e.target.name === 'text') { 
      this.setState({ 
        text : e.target.value, 
      }); 
    } 
  } 
 
  render() { 
    return ( 
      <div className="App"> 
       <h1>Chat</h1> 
        <CommentBox text={this.state.text} userName={this.state.userName} onTextChange={this.onTextChange} /> 
      </div> 
    ); 
  } 
} 
 
export default App; 
CommentBox.jsを変更していきます。上記でCommentBoxコンポーネントに渡されたpropsはpropsとして以下コンポーネントに渡されます。親コンポーネントから渡されたpropsはprops.usernameのようにして子コンポーネント内で参照できます。

// CommentBox.js 
 
import React from 'react'; 
 
export const CommentBox = (props) => ( 
  <div> 
    <input 
      name='userName' 
      placeholder='username' 
      value={props.userName} 
      onChange={props.onTextChange} 
    /> 
   <textarea 
      name='text' 
      placeholder="comment" 
      value={props.text} 
      onChange={props.onTextChange} 
    /> 
    <button>Comment</button> 
  </div> 
) 
CommentBoxのフィールドからテキストが入力され、Inputtextareaそれぞれvalueが変更されると、親コンポーネントからonChangeイベントハンドラーに渡されたonTextChangeが呼ばれ、this.setState()を用いて、Appコンポーネントのstateにそれぞれ保存されます。onTextChangeにはSyntheticEventと呼ばれ、引数eにそれぞれのvalueが渡されます(以下のコード内のようにメソッド内からe.target.valueのように参照できます)。

SyntheticEvent - https://reactjs.org/docs/events.html
App.jsに戻り、userNameとtextをまとめてメッセージオブジェクトとするとし、そのオブジェクトを格納する配列massagesを保存するmessages stateとCommentBoxのボタンがクリックすると呼ばれるonButtonClick()を追加し、CommentBoxへpropsとして渡します。onButtonClick()では、まず、initial stateである空のmessages配列を参照し、userNameとtext stateをオブジェクトとしてまとめて配列にpushしています。

// App.js 
 
class App extends Component { 
  constructor(props) { 
    super(props); 
 
    this.state = { 
      userName: "", 
      text : "", 
      messages : [] 
    } 
 
    this.onTextChange = this.onTextChange.bind(this); 
    this.onButtonClick = this.onButtonClick.bind(this); 
  } 
 
  onTextChange(e) { 
    if(e.target.name === 'userName') { 
      this.setState({ 
        userName : e.target.value, 
      }); 
    } else if (e.target.name === 'text') { 
      this.setState({ 
        text : e.target.value, 
      }); 
    } 
  } 
 
  onButtonClick() { 
    const currentMessages = this.state.messages; 
    currentMessages.push({userName: this.state.userName, text: this.state.text}) 
    this.setState({messages: currentMessages}); 
  } 
 
  render() { 
    return ( 
      <div className="App"> 
       <h1>Chat</h1> 
        {this.state.messages.map((m) => <h5>{m.userName}</h5>)} 
        <CommentBox text={this.props.text} userName={this.props.userName} onTextChange={this.onTextChange} onButtonClick={this.onButtonClick}/> 
      </div> 
    ); 
  } 
} 
 
export default App; 
CommentBox.jsonClickonButtonClickを設定します。

<button onClick={props.onButtonClick}>Comment</button> 
さぁ、最後にApp.jsのmessages stateに保存されているmessageをそれぞれ表示してみましょう。
renderメソッドに配列messageの要素をひとつずつ表示する{this.state.messages.map((m) => <h5>{m.userName}</h5>)}を追加しました。また、App.jsonButtonClickにボタンクリック後、フィールドをそれぞれクリアするためのthis.setState({userName: "", text: ""})を追加しました。

.... 
onButtonClick() { 
    const currentMessages = this.state.messages; 
    currentMessages.push({userName: this.state.userName, text: this.state.text}) 
    this.setState({messages: currentMessages}); 
    this.setState({userName: "", text: ""}) 
  } 
 
  render() { 
    return ( 
      <div className="App"> 
       <h1>Chat</h1> 
        {this.state.messages.map((msg, id) => <h5 key={id}>@{msg.userName}, {msg.text}</h5>)} 
        <CommentBox text={this.state.text} userName={this.state.userName} onTextChange={this.onTextChange} onButtonClick={this.onButtonClick}/> 
      </div> 
    ); 
  } 
.... 
次回は、Firebaseを使ってデータを永続化していきたいと思います。では!

コメント

このブログの人気の投稿

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-04-30 23:37:32 RSSフィード2021-04-30 23:00 分まとめ(42件)

投稿時間:2023-02-05 02:09:04 RSSフィード2023-02-05 02:00 分まとめ(9件)