ReactJS
Real Time
Reactで実装するリアルタイムチャットアプリ開発ガイド
10 分
リアルタイムのreactチャットアプリ イントロダクション 前回のガイドでは、あなたのreactアプリケーションでparse live queryサポートを迅速に有効にするヘルパーライブラリについて詳しく知りました。このライブラリは完全にtypescriptで書かれており、 @parse/react @parse/react の上に構築されています。また、現在はアルファ版です。 さて、このガイドでは、parse reactフックを使用して、シンプルなライブチャットアプリケーションを作成する現実的な状況を体験します。このアプリは、parseのlive queryの有用性を強調する2つのreactコンポーネントで構成されており、完全なライブアプリを作成するために必要なすべての情報を示します。 parse react nativeは現在アルファ版です。このライブラリはテスト中ですので、慎重に進めることをお勧めします。あなたのフィードバックは非常に感謝されますので、ライブラリを使用して、質問や最初の印象をcommunity\@back4app comにメールで送信してください。 前提条件 このチュートリアルを完了するには、以下が必要です 作成されたreactアプリと back4appに接続された 前のガイドを完了して、 parse reactフックとlive queryについての理解を深める このガイドで提供される画面レイアウトをテスト/使用したい場合は、 ant design ant design ライブラリを設定する必要があります。 目標 parseのlive queryを有効にするために、 @parse/react @parse/react フックを使用して、react上にライブチャットアプリケーションを構築することです。 1 データベースクラスの理解と作成 チャットアプリケーションは、2つの小さなデータベースクラスで構成されます ニックネーム ニックネーム と メッセージ メッセージ ニックネーム ニックネーム には 名前 名前 というテキストフィールドがあり、アプリケーション内のユーザーを表します。 メッセージ メッセージ は、2人のユーザー間で送信される任意のテキストメッセージを保持するため、 テキスト テキスト というテキストフィールドと、 送信者 送信者 と 受信者 受信者 , の2つのオブジェクトポインタフィールドが必要です。これらはすべて ニックネーム ニックネーム クラスに関連しています。 次のスニペットをback4appダッシュボードのjavascriptコンソールで実行して、これらのクラスを作成し、いくつかのサンプルでポピュレートします。 1 // create nicknames 2 let nicknamea = new parse object('nickname'); 3 nicknamea set('name', 'smartboy22'); 4 nicknamea = await nicknamea save(); 5 let nicknameb = new parse object('nickname'); 6 nicknameb set('name', 'clevergirl23'); 7 nicknameb = await nicknameb save(); 8	 9 // create message linked to nicknames 10 let message = new parse object('message'); 11 message set('text', 'hi! how are you?'); 12 message set('sender', nicknamea); 13 message set('receiver', nicknamea); 14 message = await message save(); 15 console log('success'); 2 ライブクエリの有効化 ニックネーム クラス クラス と メッセージ メッセージ クラスを作成したので、ライブクエリ機能を有効にする必要があります。back4appダッシュボードに移動し、 アプリ設定 アプリ設定 > サーバー設定 サーバー設定 > サーバーurlとライブクエリ サーバーurlとライブクエリ back4appのサブドメインを有効にした後、ライブクエリを有効にし、どのdbクラスを有効にするかを選択できます。新しいクラスを選択し、変更を保存してください。 次に行うことは、2つのコンポーネントからなるチャットアプリを作成することです、 chatsetup chatsetup と livechat livechat です。 3 チャットセットアップコンポーネントの作成 このコンポーネントは、送信者と受信者の ニックネーム ニックネーム オブジェクトを作成および設定する責任があり、 livechat livechat コンポーネント構造のコンテナとしても機能します。セットアップ部分のレイアウトには、ニックネーム用の2つの入力フィールドと、セットアップ関数をトリガーするボタンのみがあります。あなたの src src ディレクトリに chatsetup js chatsetup js (または chatsetup tsx chatsetup tsx )という新しいファイルを作成し、次のコードを使用します chatsetup js 1 import react, { usestate } from "react"; 2 import " /app css"; 3 import { button, input } from "antd"; 4 import parse from "parse"; 5 import { livechat } from " /livechat"; 6	 7 export const chatsetup = () => { 8 // state variables holding input values and results 9 const \[sendernicknameinput, setsendernicknameinput] = usestate(""); 10 const \[sendernicknameid, setsendernicknameid] = usestate(null); 11 const \[receivernicknameinput, setreceivernicknameinput] = usestate(""); 12 const \[receivernicknameid, setreceivernicknameid] = usestate(null); 13	 14 // create or retrieve nickname objects and start livechat component 15 const startlivechat = async () => { 16 const sendernicknamename = sendernicknameinput; 17 const receivernicknamename = receivernicknameinput; 18	 19 // check if user informed both nicknames 20 if (sendernicknamename === null || receivernicknamename === null) { 21 alert("please inform both sender and receiver nicknames!"); 22 return false; 23 } 24	 25 // check if sender nickname already exists, if not create new parse object 26 let sendernicknameobject = null; 27 try { 28 const senderparsequery = new parse query("nickname"); 29 senderparsequery equalto("name", sendernicknamename); 30 const senderparsequeryresult = await senderparsequery first(); 31 if ( 32 senderparsequeryresult !== undefined && 33 senderparsequeryresult !== null 34 ) { 35 sendernicknameobject = senderparsequeryresult; 36 } else { 37 sendernicknameobject = new parse object("nickname"); 38 sendernicknameobject set("name", sendernicknamename); 39 sendernicknameobject = await sendernicknameobject save(); 40 } 41 } catch (error) { 42 alert(error); 43 return false; 44 } 45	 46 // check if receiver nickname already exists, if not create new parse object 47 let receivernicknameobject = null; 48 try { 49 const receiverparsequery = new parse query("nickname"); 50 receiverparsequery equalto("name", receivernicknamename); 51 const receiverparsequeryresult = await receiverparsequery first(); 52 if ( 53 receiverparsequeryresult !== undefined && 54 receiverparsequeryresult !== null 55 ) { 56 receivernicknameobject = receiverparsequeryresult; 57 } else { 58 receivernicknameobject = new parse object("nickname"); 59 receivernicknameobject set("name", receivernicknamename); 60 receivernicknameobject = await receivernicknameobject save(); 61 } 62 } catch (error) { 63 alert(error); 64 return false; 65 } 66	 67 // set nickname objects ids, so live chat component is instantiated 68 setsendernicknameid(sendernicknameobject id); 69 setreceivernicknameid(receivernicknameobject id); 70 return true; 71 }; 72	 73 return ( 74 \<div> 75 \<div classname="header"> 76 \<img 77 classname="header logo" 78 alt="back4app logo" 79 src={ 80 "https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png" 81 } 82 /> 83 \<p classname="header text bold">{"react on back4app"}\</p> 84 \<p classname="header text">{"live query chat app"}\</p> 85 \</div> 86 \<div classname="container"> 87 {sendernicknameid === null && receivernicknameid === null && ( 88 \<div> 89 \<input 90 classname="form input" 91 value={sendernicknameinput} 92 onchange={(event) => setsendernicknameinput(event target value)} 93 placeholder={"sender (your) nickname"} 94 size="large" 95 /> 96 \<input 97 classname="form input" 98 value={receivernicknameinput} 99 onchange={(event) => setreceivernicknameinput(event target value)} 100 placeholder={"receiver (their) nickname"} 101 size="large" 102 /> 103 \<button 104 type="primary" 105 classname="form button" 106 color={"#208aec"} 107 size={"large"} 108 onclick={startlivechat} 109 > 110 start live chat 111 \</button> 112 \</div> 113 )} 114 {sendernicknameid !== null && receivernicknameid !== null && ( 115 \<livechat 116 sendernicknamename={sendernicknameinput} 117 sendernicknameid={sendernicknameid} 118 receivernicknamename={receivernicknameinput} 119 receivernicknameid={receivernicknameid} 120 /> 121 )} 122 \</div> 123 \</div> 124 ); 125 }; chatsetup tsx 1 import react, { usestate, fc, reactelement } from "react"; 2 import " /app css"; 3 import { button, input } from "antd"; 4 import { livechat } from " /livechat"; 5 import parse from "parse"; 6	 7 export const chatsetup fc<{}> = () reactelement => { 8 // state variables holding input values and results 9 const \[sendernicknameinput, setsendernicknameinput] = usestate(""); 10 const \[sendernicknameid, setsendernicknameid] = usestate\<string | null>(null); 11 const \[receivernicknameinput, setreceivernicknameinput] = usestate(""); 12 const \[receivernicknameid, setreceivernicknameid] = usestate\<string | null>(null); 13	 14 // create or retrieve nickname objects and start livechat component 15 const startlivechat = async () promise\<boolean> => { 16 const sendernicknamename string = sendernicknameinput; 17 const receivernicknamename string = receivernicknameinput; 18	 19 // check if user informed both nicknames 20 if (sendernicknamename === "" || receivernicknamename === "") { 21 alert("please inform both sender and receiver nicknames!"); 22 return false; 23 } 24	 25 // check if sender nickname already exists, if not create new parse object 26 let sendernicknameobject parse object | null = null; 27 try { 28 const senderparsequery parse query = new parse query("nickname"); 29 senderparsequery equalto("name", sendernicknamename); 30 const senderparsequeryresult parse object | undefined = await senderparsequery first(); 31 if ( 32 senderparsequeryresult !== undefined 33 ) { 34 sendernicknameobject = senderparsequeryresult; 35 } else { 36 sendernicknameobject = new parse object("nickname"); 37 if (sendernicknameobject !== null) { 38 sendernicknameobject set("name", sendernicknamename); 39 sendernicknameobject = await sendernicknameobject save(); 40 } 41 } 42 } catch (error) { 43 alert(error); 44 return false; 45 } 46	 47 // check if receiver nickname already exists, if not create new parse object 48 let receivernicknameobject parse object | null = null; 49 try { 50 const receiverparsequery parse query = new parse query("nickname"); 51 receiverparsequery equalto("name", receivernicknamename); 52 const receiverparsequeryresult parse object | undefined = await receiverparsequery first(); 53 if ( 54 receiverparsequeryresult !== undefined 55 ) { 56 receivernicknameobject = receiverparsequeryresult; 57 } else { 58 receivernicknameobject = new parse object("nickname"); 59 if (receivernicknameobject !== null) { 60 receivernicknameobject set("name", receivernicknamename); 61 receivernicknameobject = await receivernicknameobject save(); 62 } 63 } 64 } catch (error any) { 65 alert(error); 66 return false; 67 } 68	 69 // set nickname objects ids, so live chat component is instantiated 70 if (sendernicknameobject !== null && receivernicknameobject !== null) { 71 setsendernicknameid(sendernicknameobject id); 72 setreceivernicknameid(receivernicknameobject id); 73 } 74 return true; 75 }; 76	 77 return ( 78 \<div> 79 \<div classname="header"> 80 \<img 81 classname="header logo" 82 alt="back4app logo" 83 src={ 84 "https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png" 85 } 86 /> 87 \<p classname="header text bold">{"react on back4app"}\</p> 88 \<p classname="header text">{"live query chat app"}\</p> 89 \</div> 90 \<div classname="container"> 91 {sendernicknameid === null && receivernicknameid === null && ( 92 \<div> 93 \<input 94 classname="form input" 95 value={sendernicknameinput} 96 onchange={(event) => setsendernicknameinput(event target value)} 97 placeholder={"sender (your) nickname"} 98 size="large" 99 /> 100 \<input 101 classname="form input" 102 value={receivernicknameinput} 103 onchange={(event) => setreceivernicknameinput(event target value)} 104 placeholder={"receiver (their) nickname"} 105 size="large" 106 /> 107 \<button 108 type="primary" 109 classname="form button" 110 color={"#208aec"} 111 size={"large"} 112 onclick={startlivechat} 113 > 114 start live chat 115 \</button> 116 \</div> 117 )} 118 {sendernicknameid !== null && receivernicknameid !== null && ( 119 \<livechat 120 sendernicknamename={sendernicknameinput} 121 sendernicknameid={sendernicknameid} 122 receivernicknamename={receivernicknameinput} 123 receivernicknameid={receivernicknameid} 124 /> 125 )} 126 \</div> 127 \</div> 128 ); 129 }; 注意してください、 livechat livechat コンポーネントは、セットアッププロセスが成功し、すべての状態変数が適切に設定されたときのみ初期化され、レンダリングされます。同様に、セットアップ入力はプロセスの後に隠され、子コンポーネントのレイアウトがレンダリングされます。 4 ライブチャットコンポーネントの作成 この livechat livechat コンポーネントは、初期化時にパラメータとして渡された2つの メッセージ メッセージ の表示と送信を処理します。このコンポーネントでは、最終的に useparsequery useparsequery フックを @parse/react @parse/react から使用して、このチャットインスタンスに関連する メッセージ メッセージ オブジェクトを取得するライブクエリを設定します。あなたの src src ディレクトリに livechat js livechat js (または livechat tsx livechat tsx )という新しいファイルを作成し、以下のコードを挿入します。 livechat js 1 import react, { usestate } from "react"; 2 import " /app css"; 3 import { button, input, tooltip } from "antd"; 4 import { syncoutlined } from "@ant design/icons"; 5 import parse from "parse"; 6 import { useparsequery } from "@parse/react"; 7	 8 export const livechat = (props) => { 9 // state variable to hold message text input 10 const \[messageinput, setmessageinput] = usestate(""); 11	 12 // create parse query for live querying using useparsequery hook 13 const parsequery = new parse query("message"); 14 // get messages that involve both nicknames 15 parsequery containedin("sender", \[ 16 props sendernicknameid, 17 props receivernicknameid, 18 ]); 19 parsequery containedin("receiver", \[ 20 props sendernicknameid, 21 props receivernicknameid, 22 ]); 23 // set results ordering 24 parsequery ascending("createdat"); 25	 26 // include nickname fields, to enable name getting on list 27 parsequery includeall(); 28	 29 // declare hook and variables to hold hook responses 30 const { islive, isloading, issyncing, results, count, error, reload } = 31 useparsequery(parsequery, { 32 enablelocaldatastore true, // enables cache in local datastore (default true) 33 enablelivequery true, // enables live query for real time update (default true) 34 }); 35	 36 // message sender handler 37 const sendmessage = async () => { 38 try { 39 const messagetext = messageinput; 40	 41 // get sender and receiver nickname parse objects 42 const sendernicknameobjectquery = new parse query("nickname"); 43 sendernicknameobjectquery equalto("objectid", props sendernicknameid); 44 let sendernicknameobject = await sendernicknameobjectquery first(); 45 const receivernicknameobjectquery = new parse query("nickname"); 46 receivernicknameobjectquery equalto("objectid", props receivernicknameid); 47 let receivernicknameobject = await receivernicknameobjectquery first(); 48	 49 // create new message object and save it 50 let message = new parse object("message"); 51 message set("text", messagetext); 52 message set("sender", sendernicknameobject); 53 message set("receiver", receivernicknameobject); 54 message save(); 55	 56 // clear input 57 setmessageinput(""); 58 } catch (error) { 59 alert(error); 60 } 61 }; 62	 63 // helper to format createdat value on message 64 const formatdatetotime = (date) => { 65 return `${date gethours()} ${date getminutes()} ${date getseconds()}`; 66 }; 67	 68 return ( 69 \<div> 70 \<div classname="flex between"> 71 \<h2 class="list heading">{`${props sendernicknamename} sending, ${props receivernicknamename} receiving!`}\</h2> 72 \<tooltip title="reload"> 73 \<button 74 onclick={reload} 75 type="primary" 76 shape="circle" 77 icon={\<syncoutlined />} 78 /> 79 \</tooltip> 80 \</div> 81 {results && ( 82 \<div classname="messages"> 83 {results 84 sort((a, b) => a get("createdat") > b get("createdat")) 85 map((result) => ( 86 \<div 87 key={result id} 88 classname={ 89 result get("sender") id === props sendernicknameid 90 ? "message sent" 91 "message received" 92 } 93 > 94 \<p classname="message bubble">{result get("text")}\</p> 95 \<p classname="message time"> 96 {formatdatetotime(result get("createdat"))} 97 \</p> 98 \<p classname="message name"> 99 {result get("sender") get("name")} 100 \</p> 101 \</div> 102 ))} 103 \</div> 104 )} 105 \<div classname="new message"> 106 \<h2 classname="new message title">new message\</h2> 107 \<input 108 classname="form input" 109 value={messageinput} 110 onchange={(event) => setmessageinput(event target value)} 111 placeholder={"your message "} 112 size="large" 113 /> 114 \<button 115 type="primary" 116 classname="form button" 117 color={"#208aec"} 118 size={"large"} 119 onclick={sendmessage} 120 > 121 send message 122 \</button> 123 \</div> 124 \<div> 125 {isloading && \<p>{"loading…"}\</p>} 126 {issyncing && \<p>{"syncing…"}\</p>} 127 {islive ? \<p>{"status live"}\</p> \<p>{"status offline"}\</p>} 128 {error && \<p>{error message}\</p>} 129 {count && \<p>{`count ${count}`}\</p>} 130 \</div> 131 \</div> 132 ); 133 }; livechat tsx 1 import react, { usestate, fc, reactelement } from "react"; 2 import " /app css"; 3 import { button, input, tooltip } from "antd"; 4 import { syncoutlined } from "@ant design/icons"; 5 import parse from "parse"; 6 import { useparsequery } from "@parse/react"; 7	 8 type livechatprops = { 9 sendernicknameid string, 10 sendernicknamename string, 11 receivernicknameid string, 12 receivernicknamename string, 13 } 14	 15 export const livechat fc\<livechatprops> = (props livechatprops) reactelement => { 16 const parse = require("parse/dist/parse min js"); 17 // state variable to hold message text input 18 const \[messageinput, setmessageinput] = usestate(""); 19	 20 // create parse query for live querying using useparsequery hook 21 const parsequery parse query = new parse query("message"); 22 // get messages that involve both nicknames 23 parsequery containedin("sender", \[ 24 props sendernicknameid, 25 props receivernicknameid, 26 ]); 27 parsequery containedin("receiver", \[ 28 props sendernicknameid, 29 props receivernicknameid, 30 ]); 31 // set results ordering 32 parsequery ascending("createdat"); 33	 34 // include nickname fields, to enable name getting on list 35 parsequery includeall(); 36	 37 // declare hook and variables to hold hook responses 38 const { islive, isloading, issyncing, results, count, error, reload } = 39 useparsequery(parsequery, { 40 enablelocaldatastore true, // enables cache in local datastore (default true) 41 enablelivequery true, // enables live query for real time update (default true) 42 }); 43	 44 // message sender handler 45 const sendmessage = async () => { 46 try { 47 const messagetext string = messageinput; 48	 49 // get sender and receiver nickname parse objects 50 const sendernicknameobjectquery parse query = new parse query("nickname"); 51 sendernicknameobjectquery equalto("objectid", props sendernicknameid); 52 let sendernicknameobject parse object | undefined = await sendernicknameobjectquery first(); 53 const receivernicknameobjectquery parse query = new parse query("nickname"); 54 receivernicknameobjectquery equalto("objectid", props receivernicknameid); 55 let receivernicknameobject parse object | undefined = await receivernicknameobjectquery first(); 56	 57 // create new message object and save it 58 let message parse object = new parse object("message"); 59 message set("text", messagetext); 60 message set("sender", sendernicknameobject); 61 message set("receiver", receivernicknameobject); 62 message save(); 63	 64 // clear input 65 setmessageinput(""); 66 } catch (error any) { 67 alert(error); 68 } 69 }; 70	 71 // helper to format createdat value on message 72 const formatdatetotime = (date date) string => { 73 return `${date gethours()} ${date getminutes()} ${date getseconds()}`; 74 }; 75	 76 return ( 77 \<div> 78 \<div classname="flex between"> 79 \<h2 class="list heading">{`${props sendernicknamename} sending, ${props receivernicknamename} receiving!`}\</h2> 80 \<tooltip title="reload"> 81 \<button 82 onclick={reload} 83 type="primary" 84 shape="circle" 85 icon={\<syncoutlined />} 86 /> 87 \</tooltip> 88 \</div> 89 {results && ( 90 \<div classname="messages"> 91 {results 92 sort((a, b) => a get("createdat") > b get("createdat")) 93 map((result) => ( 94 \<div 95 key={result id} 96 classname={ 97 result get("sender") id === props sendernicknameid 98 ? "message sent" 99 "message received" 100 } 101 > 102 \<p classname="message bubble">{result get("text")}\</p> 103 \<p classname="message time"> 104 {formatdatetotime(result get("createdat"))} 105 \</p> 106 \<p classname="message name"> 107 {result get("sender") get("name")} 108 \</p> 109 \</div> 110 ))} 111 \</div> 112 )} 113 \<div classname="new message"> 114 \<h2 classname="new message title">new message\</h2> 115 \<input 116 classname="form input" 117 value={messageinput} 118 onchange={(event) => setmessageinput(event target value)} 119 placeholder={"your message "} 120 size="large" 121 /> 122 \<button 123 type="primary" 124 classname="form button" 125 color={"#208aec"} 126 size={"large"} 127 onclick={sendmessage} 128 > 129 send message 130 \</button> 131 \</div> 132 \<div> 133 {isloading && \<p>{"loading…"}\</p>} 134 {issyncing && \<p>{"syncing…"}\</p>} 135 {islive ? \<p>{"status live"}\</p> \<p>{"status offline"}\</p>} 136 {error && \<p>{error message}\</p>} 137 {count && \<p>{`count ${count}`}\</p>} 138 \</div> 139 \</div> 140 ); 141 }; このコンポーネント構造を4つの部分に分解して、レイアウトをよりよく理解できるようにしましょう 最上部には、メッセージの parse query parse query と parse react フックのセットアップがあります。ここでは、 props props パラメータがどのように使用されて、取得したいメッセージをクエリで取得できるようにしているかがわかります; その後、 sendmessage sendmessage 関数があり、これは新しい message message オブジェクトを作成し、このチャットインスタンスで使用される nickname nickname に関連付けます。また、メッセージの日付値をフォーマットするためのヘルパー関数もあります; さて、jsxコード内には、parse react フック変数に関連するステータスフラグと接続再読み込みボタンがあります; 最後に、 message message リストが表示され、レンダリングされたリストアイテムのスタイルはその送信者の値によって決まります。下部には、シンプルなテキスト入力とボタンを使ったメッセージ送信部分があります。 最後に、これらのクラスをあなたの app css app css ファイルに追加してください。そうすれば、コンポーネントのレイアウトを完全にレンダリングできます。それでは、アプリをテストしてみましょう。 app css 1 @import ' antd/dist/antd css'; 2	 3 html { 4 box sizing border box; 5 outline none; 6 overflow auto; 7 } 8	 9 body { 10 margin 0; 11 background color #fff; 12 } 13	 14 , 15 before, 16 after { 17 margin 0; 18 padding 0; 19 box sizing inherit; 20 } 21	 22 h1, 23 h2, 24 h3, 25 h4, 26 h5, 27 h6 { 28 margin 0; 29 font weight bold; 30 } 31	 32 li { 33 list style none; 34 } 35	 36 p { 37 margin 0; 38 } 39	 40 flex between { 41 display flex; 42 align items center; 43 justify content space between; 44 } 45	 46 list heading { 47 font weight bold; 48 } 49	 50 app { 51 text align center; 52 } 53	 54 container { 55 width 100%; 56 max width 500px; 57 margin auto; 58 padding 20px 0; 59 text align left; 60 } 61	 62 header { 63 align items center; 64 padding 25px 0; 65 background color #208aec; 66 } 67	 68 header logo { 69 height 55px; 70 margin bottom 20px; 71 object fit contain; 72 } 73	 74 header text bold { 75 margin bottom 3px; 76 color rgba(255, 255, 255, 0 9); 77 font size 16px; 78 font weight bold; 79 } 80	 81 header text { 82 color rgba(255, 255, 255, 0 9); 83 font size 15px; 84 } 85	 86 heading { 87 font size 22px; 88 } 89	 90 form wrapper { 91 margin top 20px; 92 margin bottom 10px; 93 } 94	 95 form input { 96 margin bottom 20px; 97 } 98	 99 form button { 100 width 100%; 101 } 102	 103 messages { 104 margin top 25px; 105 } 106	 107 message sent { 108 position relative; 109 width 50%; 110 margin left auto; 111 } 112	 113 message received { 114 position relative; 115 width 50%; 116 } 117	 118 message bubble { 119 padding 12px; 120 border radius 25px; 121 background color rgba(0, 0, 0, 0 2); 122 } 123	 124 message sent message bubble { 125 background color #1e88e5; 126 color #fff; 127 } 128	 129 message time { 130 position absolute; 131 top 35%; 132 left 62px; 133 font size 13px; 134 color rgba(0, 0, 0, 0 35); 135 transform translatey( 50%); 136 } 137	 138 message sent message time { 139 left initial; 140 right 62px; 141 } 142	 143 message name { 144 margin top 5px; 145 color rgba(0, 0, 0, 0 55); 146 font size 13px; 147 font weight 600; 148 } 149	 150 message sent message name { 151 text align right; 152 } 153	 154 new message { 155 padding top 15px; 156 margin top 20px; 157 margin bottom 10px; 158 border top 1px solid rgba(0, 0, 0, 0 12); 159 } 160	 161 new message title { 162 margin bottom 15px; 163 } 5 チャットアプリケーションのテスト ライブチャットアプリをテストするには、 chatsetup chatsetup コンポーネントをあなたの app js app js (または app tsx app tsx ) jsxコードで宣言して呼び出してください。以下はその方法の例です app js or app tsx 1 import react from "react"; 2 import " /app css"; 3 import { initializeparse } from "@parse/react"; 4 import { chatsetup } from " /chatsetup"; 5	 6 // your parse initialization configuration goes here 7 // note the live query url instead of the regular server url 8 const parse application id = "your parse application id"; 9 // const parse server url = "https //parseapi back4app com/"; 10 const parse live query url = "https //your app name b4a io/"; 11 const parse javascript key = "your parse javascript key"; 12	 13 // initialize parse using @parse/react instead of regular parse js sdk 14 initializeparse( 15 parse live query url, 16 parse application id, 17 parse javascript key 18 ); 19	 20 function app() { 21 return ( 22 \<div classname="app"> 23 \<chatsetup /> 24 \</div> 25 ); 26 } 27	 28 export default app; コンソールで yarn start yarn start を実行してアプリを起動します。これで、チャットを開始するために送信者と受信者のニックネームを入力する必要がある次の画面が表示されるはずです。 アプリとライブクエリがどのように機能しているかをよりよく見るために、同じアプリを2つの異なるブラウザウィンドウで開き、横に並べてください。ウィンドウでメッセージを送信した直後に、ニックネームが一致し、接続がライブであれば、もう一方のウィンドウにメッセージが表示されるはずです。 結論 このガイドの最後に、リアルなアプリケーションの例でparseのライブクエリのためのparse reactフックの使い方を学びました。