FireStore - 使用新数据更新 UI,无需重新加载浏览器 [英] FireStore - Update the UI with new data without reloading the browser

查看:64
本文介绍了FireStore - 使用新数据更新 UI,无需重新加载浏览器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下组件在 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(添加了新文档");}});});

这反过来会重新渲染显示原始文本的任何组件.

另见:

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:

这篇关于FireStore - 使用新数据更新 UI,无需重新加载浏览器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆