reactjs - FireStore - 使用新数据更新 UI 而无需重新加载浏览器
问题描述
我使用以下组件在 Google Cloud FireStore 集合中添加新数据:
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>
);
};
导出默认 AddCard;
添加按钮有效,我可以看到新数据已添加到 Google 服务器上的集合中,但是为了能够查看这些新数据,我必须刷新页面。
为了修复它,我决定使用onSnapshot函数,如下所示:
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;
但是,尽管新数据已添加到 FireStore 集合中,但我在页面上看不到任何更改。我仍然必须刷新(重新加载)浏览器才能看到这些更改。我究竟做错了什么?
解决方案
renderDocList
没有人会在这个片段中看到调用的结果:
db.collection('FlashCards').onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
changes.forEach((change) => {
if (change.type === 'added') {
renderDocList();
}
});
});
如果你想更新 UI,你需要告诉 React 有新数据要渲染。这就是useState
钩子的用途。它不能完全了解您的代码如何影响正在呈现的内容,但您需要调用一个 setter 来修改组件呈现的状态。
所以说你的原始文本来自数据库,你会这样做:
db.collection('FlashCards').onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
changes.forEach((change) => {
if (change.type === 'added') {
setNewOriginalText("new document added");
}
});
});
反过来,这将重新渲染任何显示原始文本的组件。
另见:
- 无法使用 React 获取 firebase 集合,我在其中使用
setState
而不是useState
钩子。 - NodeJs/Firestore/React- 将 Firestore 查询结果存储到状态中
推荐阅读
- tabulator - 为每个单元格制作自定义工具提示
- javascript - 返回续集中行的自定义值?
- react-native - 如何从数组中为 AsyncSelect 设置样式边框颜色 - ReactNative?
- vue.js - 在 vue-cli3 中为构建文件提供静态文件名
- regex - 即使您不在正确的组中,Perl 正则表达式分组结果也会添加额外的字符
- python - 运行成本 sigmoid 成本函数时出错
- javascript - 多次调用数据库无法正常工作
- matlab - 如何比较一维矩阵的值?
- c# - 为什么 char 数组在控制台上显示内容,而 string 和 int 数组在 c# 中却没有?
- kubernetes - 重启节点后,由于 weave IP 不足,Pod 卡在 containerCreating 状态