0
votes

Using the following component I can connect to a Cloud FireStore collection and add new documents in to it.

Now, I'm trying to use the Real-Time-Data by using onSnapshot method, but I'm not sure how to implement it in my code.

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 className='list'>
      <li className='list__item list__item--add' key={nextNumber}>
        <input
          type='text'
          defaultValue={nextNumber}
        />
        <div>
            <textarea
              onChange={(e) => setNewOriginalText(e.target.value)}
            />
          )}
        </div>
        <textarea
          onChange={(e) => setNewTranslatedText(e.target.value)}
        />
        <button onClick={onAdd}>
          Add
        </button>
      </li>
    </ul>
  );
};

export default AddCard;

This is what I tried:

import React, { useState, useEffect } 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),
      })
      .onSnapshot((snapshot) => {
        let changeds = snapshot.docChanges();
        changeds.forEach((change) => {
          if (change.type === 'added') {
            renderDocList();
          }
        });
      });
  };

  const renderDocList = () => {
    return (
      <ul>
        <li key={nextNumber}>
          <input
            type='text'
            defaultValue={nextNumber}
          />
          <div>
              <textarea
                onChange={(e) => setNewOriginalText(e.target.value)}
              />
            )}
          </div>
          <textarea
            onChange={(e) => setNewTranslatedText(e.target.value)}
          />
          <button onClick={onAdd}>
            Add
          </button>
        </li>
      </ul>
    );
  };

  return (
    <>
      {renderDocList()}
    </>
  );
};

export default AddCard;

But once I click on the Add button, I get this error:

Unhandled Rejection (TypeError): firebase__WEBPACK_IMPORTED_MODULE_1_.db.collection(...).add(...).onSnapshot is not a function

1

1 Answers

0
votes

onSnapshot isn't working with add. The idea is that you want to subscribe to the collection so that whenever changes happen it will tell you.

so you need to do it this way

import React, { useState, useEffect } from 'react';
import { db } from '../firebase';
  db.collection('FlashCards')
     .onSnapshot((snapshot) => {
        let changeds = snapshot.docChanges();
        changeds.forEach((change) => {
          if (change.type === 'added') {
            renderDocList();
          }
        });
  });
  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
                onChange={(e) => setNewOriginalText(e.target.value)}
              />
            )}
          </div>
          <textarea
            onChange={(e) => setNewTranslatedText(e.target.value)}
          />
          <button onClick={onAdd}>
            Add
          </button>
        </li>
      </ul>
    );
  };

  return (
    <>
      {renderDocList()}
    </>
  );
};

export default AddCard;

you can find other examples here