見出し画像

react-native-gifted-chat の使い方

「react-native-gifted-chat」の使い方をまとめました。


前回

1. react-native-gifted-chat

react-native-gifted-chat」は、「React Native」で利用できるチャットUIコンポーネントライブラリです。チャットアプリケーションを簡単に作成できるように設計されています。

・react-native-webable (since 0.10.0) web configuration
・TypeScript (since 0.8.0)
・完全にカスタマイズ可能なコンポーネント
・コンポーザーアクション
(写真の添付など)
・以前のメッセージを読み込む
・メッセージをクリップボードにコピー
・タッチ可能なリンク
(react-native-parsed-text)
・ユーザーのイニシャルとしてのアバター
・ローカライズされた日付
・複数行の TextInput
・キーボードを回避した InputToolbar
・Redux のサポート
・システムメッセージ
・クイック返信メッセージ
(Bot)
・入力インジケータ (react-native-typing-animation)

2. react-native-gifted-chat の使い方

「react-native-gifted-chat」の使い方の手順は次のとおりです。

2-1. セットアップ

(1) React Nativeプロジェクトの生成。

npx react-native init my_app
cd my_app

(2) パッケージのインストール。
「uuid」「@types/uuid」「react-native-get-random-values」はUUIDのためのパッケージになります。

npm install react-native-gifted-chat
npm install uuid
npm install --save-dev @types/uuid 
npm install react-native-get-random-values

2-2. iOSのセットアップ

(1) iOSのセットアップ。

cd ios
pod install
cd ..

(2) workspaceを開き、署名し、iPhoneにインストールできることを確認。

2-3. コードの編集と実行

(1) index.jsに「import 'react-native-get-random-values';」を追加。
UUIDの利用に必要です。

・index.js

import 'react-native-get-random-values';
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

(2) コードの編集。

・App.tsx

import React, { useState } from "react";
import { GiftedChat, IMessage } from "react-native-gifted-chat";
import { v4 as uuidv4 } from "uuid";

// アプリ
function App(): React.JSX.Element {
  const [messages, setMessages] = useState<IMessage[]>([]); // メッセージリスト

  // アシスタントメッセージの作成
  const reply = (): IMessage => {
    return {
      _id: uuidv4(),
      text: "こんにちは!",
      createdAt: new Date(),
      user: {
        _id: 2,
        name: "Assistant",
        avatar: "https://ui-avatars.com/api/?background=0dbc3f&color=FFF&name=A",
      },
    };
  };

  // 送信ボタン押下時に呼ばれる
  const onSend = (newMessages: IMessage[] = []) => {
    // ユーザーメッセージの追加
    setMessages((previousMessages) =>
      GiftedChat.append(previousMessages, newMessages)
    );

    // アシスタントメッセージの追加
    setMessages((previousMessages) =>
      GiftedChat.append(previousMessages, [reply()])
    );
  };

  // ユーザーの準備
  const user = {
    _id: 1,
    name: "User",
  };

  return (
    <GiftedChat
      messages={messages}
      placeholder="メッセージを入力"
      onSend={messages => onSend(messages)}
      user={user}
      locale="ja"
    />
  );
};

export default App;

IMessageのデータ型は次のとおりです。

export interface IMessage {
    _id: string | number // ID
    text: string // テキスト
    createdAt: Date | number // 生成日
    user: User // ユーザー
    image?: string // 画像
    video?: string // 動画
    audio?: string // オーディオ
    system?: boolean // システム
    sent?: boolean // チェックマークで送信済みを表現
    received?: boolean // 2つのチェックマークで受信済みを表現
    pending?: boolean // クロックローダーで保留中を表現
    quickReplies?: QuickReplies // 追加のカスタムパラメータ
}

(2) コードの実行。

npm start

3. 警告対応

react-native-gifted-chat v2.4.0」ではAvaterで警告がでます。
解決方法は以下で紹介されています。

Warning: Avatar: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead. #2498

4. UIのカスタマイズ

(1) コードの編集。
「カスタムアバター」と「カスタム送信」を実装して、「renderAvatar」と「renderSend」で設定します。

import React, { useState } from "react";
import { GiftedChat, IMessage, Send } from "react-native-gifted-chat";
import { View, Image, StyleSheet, Text } from "react-native";
import { v4 as uuidv4 } from "uuid";

// カスタムアバター
const CustomAvatar = (props: any) => {
  return (
    <View>
      <Image
        source={{ uri: props.currentMessage.user.avatar }}
        style={{ width: 40, height: 40, borderRadius: 20 }}
      />
    </View>
  );
};

// カスタム送信
const CustomSend = (props: any) => {
  return (
    <Send {...props}>
      <View style={styles.sendButton}>
        <Text style={styles.sendButtonText}>送信</Text>
      </View>
    </Send>
  );
};

// スタイルシート
const styles = StyleSheet.create({
  sendButton: {
    backgroundColor: "#0dbc3f",
    borderRadius: 8,
    padding: 8,
    marginBottom: 4,
    marginRight: 4,
  },
  sendButtonText: {
    color: "#fff",
    fontWeight: "bold",
  },
});

// アプリ
function App(): React.JSX.Element {
  const [messages, setMessages] = useState<IMessage[]>([]); // メッセージリスト

  // アシスタントメッセージの作成
  const reply = (): IMessage => {
    return {
      _id: uuidv4(),
      text: "こんにちは!",
      createdAt: new Date(),
      user: {
        _id: 2,
        name: "Assistant",
        avatar: "https://ui-avatars.com/api/?background=0dbc3f&color=FFF&name=A",
      },
    };
  };

  // 送信ボタン押下時に呼ばれる
  const onSend = (newMessages: IMessage[] = []) => {
    // ユーザーメッセージの追加
    setMessages((previousMessages) =>
      GiftedChat.append(previousMessages, newMessages)
    );

    // アシスタントメッセージの追加
    setMessages((previousMessages) =>
      GiftedChat.append(previousMessages, [reply()])
    );
  };

  // ユーザーの準備
  const user = {
    _id: 1,
    name: "User",
  };

  return (
    <GiftedChat
      messages={messages}
      placeholder="メッセージを入力"
      onSend={messages => onSend(messages)}
      user={user}
      locale="ja"
      renderAvatar={(props) => <CustomAvatar {...props} />}
      renderSend={(props) => <CustomSend {...props} />}
    />
  );
};

export default App;

(2) コードの実行。

npm start

5. サーバとの通信

reply()をサーバで実装します。

5-1. サーバの実装

PythonのFastAPIで実装します。

(1) Python仮想環境の準備。

(2)  パッケージのインストール。

pip install fastapi uvicorn 

(3) サーバの実装。

・main.py

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from uuid import uuid4
from datetime import datetime

app = FastAPI()

# メッセージ
class Message(BaseModel):
    _id: str
    text: str
    createdAt: datetime
    user: dict

# メッセージリクエスト
class MessageRequest(BaseModel):
    message: Message

# アシスタントメッセージの作成
def create_assistant_message() -> Message:
    return Message(
        _id=str(uuid4()),
        text="こんにちは!",
        createdAt=datetime.now(),
        user={
            "_id": 2,
            "name": "Assistant",
            "avatar": "https://ui-avatars.com/api/?background=0dbc3f&color=FFF&name=A"
        }
    )

# チャットエンドポイント
@app.post("/api/chat")
async def chat_endpoint(message_request: MessageRequest):
    # メッセージリクエストの取得
    user_message = message_request.message

    # アシスタントメッセージの作成
    assistant_message = create_assistant_message()
    return {"message": assistant_message}

(4) サーバの実行。

uvicorn main:app --host 0.0.0.0 --port 8000

5-2. クライアントの実装

(1) reply()の編集。
サーバーにユーザーメッセージを渡して、アシスタントメッセージを受け取ります。<ローカルIP>は、サーバを起動したローカルのIPを指定します。

・App.tsxの一部

  // アシスタントメッセージの作成
  const reply = async (userMessage: IMessage): Promise<IMessage> => {
    const response = await fetch("http://<ローカルIP>:8000/api/chat", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ message: userMessage }),
    });
    const data = await response.json();
    return data.message;
  };

  // 送信ボタン押下時に呼ばれる
  const onSend = async (newMessages: IMessage[] = []) => {
    // ユーザーメッセージの追加
    setMessages((previousMessages) =>
      GiftedChat.append(previousMessages, newMessages)
    );

    // アシスタントメッセージの追加
    const assistantMessage = await reply(newMessages[0]);
    setMessages((previousMessages) =>
      GiftedChat.append(previousMessages, [assistantMessage])
    );
  };

次回




この記事が気に入ったらサポートをしてみませんか?