質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • React.js

    829questions

    Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

  • Firebase

    604questions

    Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

  • React Native

    181questions

    React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

gifted chatでmessageをDBからFetchしたい(react native)

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 298

yamady

score 148

閲覧いただきまして、ありがとうござますmm

React NativeとFirebaseでチャット機能を実装したいと考えています。
「RNでチャットを実装するならコレ!」というので名高い、gifted chatを使っているのですが最後の最後(?)で詰まってしまっています・・・。(泣

 エラー(困っていること) 

Firebaseに入っているroom(チャットルーム)に入っているmessages(メッセージ一覧)を取ってくることには成功しているが、messageに分けることができない。

 開発環境&ソースコード

使っているライブラリ(バージョン)は下記となります。

react-native ^0.52.3
react-native-firebase 3.2.2
react-native-gifted-chat 0.4.3

Message.js

/**
* @flow
*
* The Message is a screen to communicate with User
*/
import _ from 'lodash';
import React from 'react';
import { StyleSheet, TouchableOpacity, View, Text, ListView } from 'react-native';
import Icon from '../../ui/components/Icon';
import * as Theme from '../../theme';
import Screen from '../../ui/components/Screen';
import { sendMessage, messagesFetch } from '../../ui/redux/messageActions';
import firebase from 'react-native-firebase';
import { connect } from 'react-redux';
import { GiftedChat, Bubble, Send } from 'react-native-gifted-chat';

const styles = StyleSheet.create({
  headerIcon: {
    paddingHorizontal: 15
  }
});

class Message extends React.Component {
  static navigationOptions = ({ navigation }) => {
    return {
      headerTitle: `${navigation.state.params.room.user.name}`,
      headerLeft: (
        <TouchableOpacity
          onPress={()=> navigation.goBack()}
          style={styles.headerIcon}
        >
          <Icon name='chevron-left' size={28} style={{color: '#fff'}}/>
        </TouchableOpacity>
      ),
      headerStyle: {
        backgroundColor: Theme.PRIMARY,
      },
      headerTitleStyle: {
        color: '#fff',
        fontWeight: 'bold'
      }
    };
  };

  state = {
    messages: [],
  }

  componentWillMount() {
    const room = this.props.navigation.state.params.room;
    this.props.messagesFetch(room);

    this.createDataSource(this.props);
  }

  componentWillReceiveProps(nextProps) {
    this.createDataSource(nextProps);
  }

  createDataSource({ messages }) {
    const ds = new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    });

    this.dataSource = ds.cloneWithRows(messages);
    // ここまでのmessagesは配列で取ってこれている
    console.log('messages', messages);
  }

  onSend = (message) => {
    const room = this.props.navigation.state.params.room;
    // this.setState((previousState) => ({
    //     messages: GiftedChat.append(previousState.messages, messages),
    // }));
    this.props.sendMessage({
      message,
      room
    });
  }

 // ここでエラーになる(messageが取れてない)
  componentDidMount(message) {
    this.setState((previousState) => {
      return {
        messages: GiftedChat.append(previousState.messages, message),
      };
    });
  };

  render() {
    const { currentUser } = firebase.auth();
    return (
      <Screen>
        <GiftedChat
          messages={this.state.messages}
          onSend={this.onSend.bind(this)}
          user={{
            _id: currentUser.uid
          }}
        />
      </Screen>
    );
  }
}

const mapStateToProps = (state) => {
  const messages = _.map(state.messages, (val, uid) => {
    return { ...val, uid };
  });

  const { text, user, createdAt, _id } = state.messageForm;
  return { text, user, createdAt, _id, messages };
};

export default connect(mapStateToProps, {
  sendMessage,
  messagesFetch
})(Message);

messageActions.js

/**
* Builds an action to request
*/
export const sendMessage = ({ message, room }) => {
  const { currentUser } = firebase.auth();
  return (dispatch) => {
    firebase.database().ref(`/rooms/${room.roomId}/messages/`)
    .push({
      text: message[0].text,
      user: message[0].user,
      createdAt: firebase.database.ServerValue.TIMESTAMP,
    })
    .then(() => {
      dispatch({ type: 'message_create' });
    });
  }
}

/**
* Builds an action to notification fetch action
*/
export const messagesFetch = (room) => {
  return (dispatch) => {
    firebase.database().ref(`/rooms/${room.roomId}/messages/`)
    .once('value', snapshot => {
      dispatch({ type: 'messages_fetch_success', payload: snapshot.val() })
    });
  };
};

 参考ソース

↓ Gifted Chatの著者がやっているチュートリアル
https://www.youtube.com/watch?v=VTnFDc3IFag
https://github.com/FaridSafi/ChatApp

こちらはreduxを使っていないのですが、reduxを使ってできないものかと・・・。
そもそも、このやり方で合っているかの不安もあります(汗)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

 // ここでエラーになる(messageが取れてない)
  componentDidMount(message) {
    this.setState((previousState) => {
      return {
        messages: GiftedChat.append(previousState.messages, message),
      };
    });
  };

componentDidMount()の第一引数には何も渡ってこないはずです。
https://reactjs.org/docs/react-component.html#componentdidmount

なので、そこでmessageが取れないのは当然かと思います。

また、componentDidMount()の中で、previousState.messagesstateの中のmessagesを参照しようとしていますが、このライフサイクルのタイミングではまだ、state内のmessages[]と空の配列のままですよね?

componentWillMount() {
    const room = this.props.navigation.state.params.room;
    this.props.messagesFetch(room);

    this.createDataSource(this.props);
  }

componentDidMount()の前に呼ばれるcomponentWillMount()では、this.createDataSource(this.props)を呼んでいて、このthis.propsの中にmessageが含まれているのですよね? そして、このmessagecomponentDidMountの中で参照したいという訳なのですよね?

であれば、componentWillMountの中でstateの中にmessageを入れるか、もしくは、componentWillMountでやっていることをcomponentDidMountの方に移してしまうかすればよいのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/18 15:46

    ご丁寧な回答ありがとうございます。
    非常にわかりやすかったです。

    ```
    componentWillMount() {
    const room = this.props.navigation.state.params.room;
    this.props.messagesFetch(room);
    this.createDataSource(this.props);

    this.setState((previousState) => {
    return {
    messages: GiftedChat.append(previousState.messages, message),
    };
    });
    }
    ```

    これだと当然、messagesからmessageを取り出す作業を定義しなければならないと思うのですが、Reactで配列から全てを取り出すのに最適なやり方って何があるのでしょうか><(roomのmessagesのなかに、messageアイテムがたくさん入っている感じなのですが。。)今まではListViewのrenderRowでできていたのですが。。。汗

    キャンセル

  • 2018/04/18 15:54

    ごめんなさい、質問の意味がよく理解出来ていません。質問本文の方にコードを交えて、コメントで頂いている質問をもう少し詳しく、かつ、整理しつつ追記頂くことは可能ですか?

    キャンセル

  • 2018/04/18 16:41

    ちなみに、もし最初の回答で今回の質問自体は解決でしたら、コメント欄で頂いた内容は別質問に分けて頂けると助かります。

    キャンセル

  • 2018/04/19 05:35

    Hayatoさん、いつもご回答ありがとうございます。
    ご指摘いただいた通りですね!すみませんm(_ _)m

    別途質問を作成していきます!ありがとうございます!!

    キャンセル

  • 2018/04/19 05:41

    了解致しました!ありがとうございます!

    キャンセル

  • 2018/04/19 05:53

    https://teratail.com/questions/122533?modal=q-comp
    すみません、質問をこちらに新しく投稿することにしましたm(_ _)m

    キャンセル

  • 2018/04/19 05:57

    あ、すみません!「Hayatoさんいつもありがとうございます」は嬉しいのですが、これあると他の人が回答しづらくなると思うので、消して頂けませんでしょうか?よろしくお願い致します!今からまた寝るので明日(今日)、改めて質問みてみますね。

    キャンセル

  • 2018/04/19 06:00

    すみません、すぐに削除しますね!ごめんなさい!

    キャンセル

  • 2018/04/19 06:08

    ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • React.js

    829questions

    Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

  • Firebase

    604questions

    Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

  • React Native

    181questions

    React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。