FireStore - 使用新数据更新 UI,无需重新加载浏览器 [英] FireStore - Update the UI with new data without reloading the browser
问题描述
我使用以下组件在 Google Cloud FireStore 集合中添加新数据:
import React, { useState } from 'react';从 '../firebase' 导入 { db };const AddCard = ({ totalDoclNumbers }) =>{const [newOriginalText, setNewOriginalText] = useState([]);const [newTranslatedText, setNewTranslatedText] = useState([]);const nextNumber = totalDoclNumbers + 1;const onAdd = async() =>{等待 db.collection('FlashCards').add({原始文本:新的原始文本,翻译文本:新翻译文本,customId: Number(nextNumber),});};返回 (<ul><li key={nextNumber}><输入类型='文本'只读默认值={nextNumber}/><div><文本区域占位符='英文'onChange={(e) =>setNewOriginalText(e.target.value)}/>
<文本区域占位符='翻译'onChange={(e) =>setNewTranslatedText(e.target.value)}/><button onClick={onAdd}>添加按钮>);};
导出默认的AddCard;
添加按钮有效,我可以看到新数据已添加到 Google 服务器上的集合中,但是为了能够看到这些新数据,我必须刷新页面.
为了修复它,我决定使用 onSnapshot 函数如下:
import React, { useState } from 'react';从 '../firebase' 导入 { db };const AddCard = ({ totalDoclNumbers }) =>{const [newOriginalText, setNewOriginalText] = useState([]);const [newTranslatedText, setNewTranslatedText] = useState([]);const nextNumber = totalDoclNumbers + 1;const onAdd = async() =>{等待 db.collection('FlashCards').add({原始文本:新的原始文本,翻译文本:新翻译文本,customId: Number(nextNumber),});};const renderDocList = () =>{返回 (<ul><li key={nextNumber}><输入类型='文本'默认值={nextNumber}/><div><文本区域占位符='英文'onChange={(e) =>setNewOriginalText(e.target.value)}/>
<文本区域占位符='翻译'onChange={(e) =>setNewTranslatedText(e.target.value)}/><button onClick={onAdd}>添加按钮>);};db.collection('FlashCards').onSnapshot((snapshot) => {让更改 = snapshot.docChanges();changes.forEach((change) => {if (change.type === '已添加') {renderDocList();}});});返回<>{renderDocList()}</>;};导出默认的AddCard;
但是虽然新数据被添加到 FireStore 集合中,但我在页面上看不到任何变化.我仍然必须刷新(重新加载)浏览器才能看到这些更改.我做错了什么?
没有人会看到此代码段中 renderDocList
调用的结果:
db.collection('FlashCards').onSnapshot((snapshot) => {让更改 = snapshot.docChanges();changes.forEach((change) => {if (change.type === '已添加') {renderDocList();}});});
如果您希望 UI 更新,您需要告诉 React 有新数据要渲染.这就是 useState
钩子的用途.它没有完全了解您的代码如何影响正在呈现的内容,但您需要调用一些 setter 来修改您的组件呈现的状态.
假设您的原始文本来自数据库,您会这样做:
db.collection('FlashCards').onSnapshot((snapshot) => {让更改 = snapshot.docChanges();changes.forEach((change) => {if (change.type === '已添加') {setNewOriginalText(添加了新文档");}});});
这反过来会重新渲染显示原始文本的任何组件.
另见:
- 无法使用 React 获取 firebase 集合,我使用
setState
而不是useState
钩子. - NodeJs/Firestore/React- 将 Firestore 查询结果存储到状态中
I use the following component to add new data in a Google Cloud FireStore collection:
import React, { useState } from 'react';
import { db } from '../firebase';
const AddCard = ({ totalDoclNumbers }) => {
const [newOriginalText, setNewOriginalText] = useState([]);
const [newTranslatedText, setNewTranslatedText] = useState([]);
const nextNumber = totalDoclNumbers + 1;
const onAdd = async () => {
await db.collection('FlashCards').add({
originalText: newOriginalText,
translatedText: newTranslatedText,
customId: Number(nextNumber),
});
};
return (
<ul>
<li key={nextNumber}>
<input
type='text'
readOnly
defaultValue={nextNumber}
/>
<div>
<textarea
placeholder='English'
onChange={(e) => setNewOriginalText(e.target.value)}
/>
</div>
<textarea
placeholder='Translation'
onChange={(e) => setNewTranslatedText(e.target.value)}
/>
<button onClick={onAdd}>
Add
</button>
</li>
</ul>
);
};
export default AddCard;
The add button works and I can see that new data are added to the collection on Google server, however to be able to see those new data, I have to refresh the page.
In order to fix it, I decided to make use of onSnapshot function as follow:
import React, { useState } from 'react';
import { db } from '../firebase';
const AddCard = ({ totalDoclNumbers }) => {
const [newOriginalText, setNewOriginalText] = useState([]);
const [newTranslatedText, setNewTranslatedText] = useState([]);
const nextNumber = totalDoclNumbers + 1;
const onAdd = async () => {
await db.collection('FlashCards').add({
originalText: newOriginalText,
translatedText: newTranslatedText,
customId: Number(nextNumber),
});
};
const renderDocList = () => {
return (
<ul>
<li key={nextNumber}>
<input
type='text'
defaultValue={nextNumber}
/>
<div>
<textarea
placeholder='English'
onChange={(e) => setNewOriginalText(e.target.value)}
/>
</div>
<textarea
placeholder='Translation'
onChange={(e) => setNewTranslatedText(e.target.value)}
/>
<button onClick={onAdd}>
Add
</button>
</li>
</ul>
);
};
db.collection('FlashCards').onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
changes.forEach((change) => {
if (change.type === 'added') {
renderDocList();
}
});
});
return <>{renderDocList()}</>;
};
export default AddCard;
But although the new data get added to FireStore collection but I cannot see any changes on the page. Still I have to refresh (reload) browser to see those changes. What am I doing wrong?
Nobody is going to see the result of the renderDocList
call in this snippet:
db.collection('FlashCards').onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
changes.forEach((change) => {
if (change.type === 'added') {
renderDocList();
}
});
});
If you want the UI to update, you need to tell React that there is new data for it to render. And that's what useState
hooks are used for. It don't fully see how your code affects what is being rendered, but you'll need some call to a setter that modifies the state that your component renders.
So say that your original text comes from the database, you'd do:
db.collection('FlashCards').onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
changes.forEach((change) => {
if (change.type === 'added') {
setNewOriginalText("new document added");
}
});
});
And that in turn will then rerender any components that display the original text.
Also see:
- Can't fetch firebase collection with React, where I use
setState
instead of theuseState
hook. - NodeJs/Firestore/React- Storing Firestore query results into the state
这篇关于FireStore - 使用新数据更新 UI,无需重新加载浏览器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!