はじめに
React強くないです。
いろいろ気づいたことあればコメントいただけると学びになりますしうれしく思います。
概要
Reactでローカルストレージに保存する際には、特に何も考えずonChengeでリアルタイムに保存できます。
ただ今回の場合はDBに保存するということで一工夫ふつようになります。
その理由としては、DBに保存するという処理は軽い処理ではないためリアルタイムで処理するのが難しくなります。
結果的にはリアルタイムではありません
ローカルストレージの保存のやり方でfirebaseに保存するようなロジックを組むと
日本語入力の際、「か」と打つ場合、「k」で保存されてしまい「kかあ」と保存されてしまいます汗
このことからわかるように子音と母音からなるローマ字をどう保存するかにかかっています。
結論
Reactライブラリlodashのdebounceを使い、入力文字から一定時間経過してからDBにする記述に変えます。
さらに気を付けたいのがDBに保存しているデータをinputフィールドに表示している場合
入力しているのに入力の文字が出てこないという現象になります。
なので
・useStateで表示用
・一定時間経過したらDBに保存する用
2つの格納場所が必要になる。
※個人開発の1部抜粋
import React, { useEffect, useState, useCallback } from 'react'
//...略
const [localEnglish, setLocalEnglish] = useState(activeNote?.english || "");
// 500ms入力がないときonUpdateが発火
const saveToFirebase = useCallback(
debounce((updatedNote) => {
onUpdateNote(updatedNote);
}, 500)
,[onUpdateNote]);
// ローカル表示用のuseStateとfirebase保存用関数に値をセット
const handleEnglishChange = (e) => {
const newValue = e.target.value;
setLocalEnglish(newValue); // ローカルステートは即時更新
saveToFirebase({ // Firebaseへの保存は遅延
...activeNote,
english: newValue,
modDate: Date.now()
});
};
//...略
<div className='english_field'>
<strong>英語:</strong>
<textarea
id='english-textarea'
type="text"
placeholder='英語を記入'
value={localEnglish}
onChange={handleEnglishChange}
/>
</div>
親コンポ―ネントにifrebase更新する関数のロジック
const onUpdateNote = async (updatedNote) => {
const noteRef = doc(db, "English_words", updatedNote.id);
await updateDoc(noteRef, {
english: updatedNote.english,
japanese: updatedNote.japanese,
modDate: updatedNote.modDate
});
};
処理手順
①文字を入力するとhandleEnglishChangeが発火
【handleEnglishChange内容】
②入力した文字をsetLocalEnglishでLocalEnglishに格納し、inputフィールドのvalue属性で表示、saveToFirebaseが発火
【saveToFirebase内容】
③debounceを使って500ms秒入力がなかった時onUpdateNoteが発火
【onUpdateNote内容】
④idを特定してfirebaseの更新処理
最後に
上であげたコードだけ見ても初学者にはわからないと思うが、、、(見づらくてすみません。)
どう残していいものか悩んだがこんなかんじで書いてみた。
DBにリアルタイムで保存する必要もそこまでないし、サーバーに過負荷がかかるから
ユーザーの数や入力機会ですぐキャパがきそうw
ローカルストレージで妥協するか
登録ボタン押下で登録、更新処理するようにしDBのアクセス回数を減らすか
した方がよさそう。
自分にしかわからないであろう備忘録
上記の処理に行きつくまでにすごく時間を要した。
その際に考えていたことはuseStateで表示用を保持して、
別のデータを押下したタイミングでDBに書き込むような仕様を検討しコードを書いていた。
編集が終わったかどうかの判定をクリックにしたということ。
ただこの際に更新対象のデータも切り替わる。
その際にDBへの更新処理よりも画面の切り替わりやuseEffectの方が動作が早く、
切り替わったデータに上書きで保存されるということが起きた。
切り替わる前の更新対象のデータは更新されずに。。。
ここではまり4時間ほど止まってしまった。
DBに保存をする際は処理が重くなっているので、少し時間差を設けるか(今回)
登録ボタン、更新ボタンなどDBにアクセスするタイミングをもっとわかりやすくすることが重要だと思った。
次はハマらないように意識する。