実現したいこと
Reactとfirebaseでチャット機能を実現したいと考えていますが、その前段で思ったとおりの動作をしてくれないので、ご回答をお願いしたいと思っております。どうかよろしくお願いします。質問に回答して頂くにあたって不明点ありましたら追記、返答させて頂きます。
新しいテキストをレンダリングするために、自身で作成したInputコンポーネントにテキストを入力し、Buttonコンポーネントをクリックすると、その入力したテキストが1回レンダリングされるようにしたいのですが、1回のクリックで2回レンダリングされ入力したテキストが2回分表示されてしまします。
発生している問題
inputタグ(コンポーネント)にテキストを入力し、buttonタグ(コンポーネント)を1クリックすると2回テキストが表示される。
コードの説明
1,Chatコンポーネントがレンダリングされた直後にcomponentDidMountでloadText関数を呼び出し、firebaseに書き込んでいるテキストと投稿者を読み出して表示させています。
2,テキストをinputタグに入力し、ボタンをクリックしてhandleSubmit関数を呼び出し、firebaseに書き込みを行う。
3,firebaseへの書き込みが発生した時点で、loadtext関数内部のonSnapshotが作動する。書き込みがされた最新の状態firebaseを読み込み、それをconstructor内部にsetStateしrender()を呼び出す。
私の認識では3でsetStateを一度しか実行していないので、レンダリングも1回しかされないという認識ですが、2回レンダリングうまくいきません。ちなみに、2回表示されるテキストについてコンソールで確認すると、先に表示された方のserverTimeStampがnullで、後に表示された方に正しく値が入っているという違いがありました。
該当のソースコード
chat.component.jsx
JavaScript
1import React from 'react' 2import './chat.styles.scss' 3import Input from '../../component/input/input.component' 4import Button from '../../component/button/button.component' 5import {Link} from 'react-router-dom' 6import {auth,firestore, serverTimeStamp} from '../../firebase/firebase.utils' 7 8class Chat extends React.Component { 9 constructor(){ 10 super() 11 12 this.state={ 13 text:'', 14 displayName:'', 15 uid:'', 16 message:[] 17 } 18 } 19 20 loadText = () =>{ 21 22 firestore.collection('text').orderBy('serverTimeStamp','desc').onSnapshot(snapshot => { 23 24 snapshot.docChanges().forEach(change => { 25 if (change.type == 'removed'){ 26 27 } else { 28 const {text,displayName,serverTimeStamp} = change.doc.data() 29 const message = this.state.message 30 const obj = {text:text,displayName:displayName,serverTimeStamp:serverTimeStamp,id:change.doc.id} 31 this.setState({message:message.concat(obj)}) 32 } 33 34 }) 35 36 }) 37 38 } 39 40 41 componentDidMount(){ 42 auth.onAuthStateChanged(async (user) =>{ 43 if(!user){ 44 alert('ログインしてください') 45 this.props.history.push('/') 46 } else{ 47 const {uid,displayName} = user 48 this.setState({displayName:displayName,uid:uid}) 49 } 50 }) 51 52 this.loadText() 53 } 54 55 56 signOut=()=>{ 57 auth.signOut() 58 } 59 60 61 handleChange = (e) => { 62 const {value} =e.target 63 this.setState({text:value}) 64 } 65 66 handleSubmit = (e) => { 67 e.preventDefault() 68 69 firestore.collection('text').add({ 70 displayName:this.state.displayName, 71 uid:this.state.uid, 72 text:this.state.text, 73 serverTimeStamp:serverTimeStamp() 74 }) 75 this.setState({text:''}) 76 } 77 78 render(){ 79 const convesation= this.state.message.map((message,index) => { 80 return( 81 <div className='message' key={index} > 82 <div>{message.text}</div> 83 <div className='contributor'>投稿者:{message.displayName}</div> 84 </div> 85 ) 86 }) 87 return( 88 89 <div className='chat'> 90 91 <div className='convesation-area'> 92 {convesation} 93 </div> 94 95 <form onSubmit={this.handleSubmit}> 96 <Input 97 type='text' 98 name='text' 99 handleChange={this.handleChange} 100 value={this.state.text} 101 placeholder='テキストを入力してください' 102 /> 103 <Button 104 chlldren='送信' 105 /> 106 </form> 107 <Link className='signout' to='/' onClick={this.signOut}>サインアウト</Link> 108 </div> 109 ) 110 } 111 112} 113 114export default Chat
補足情報(FW/ツールのバージョンなど)
・環境
OS:Windows10
・FWなどののバージョン
"firebase": "^7.15.5",
"node-sass": "^4.14.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1""
"node.js" v12.16.1
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。