Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useDocumentData fails to update when read permission is not longer denied #291

Open
amiregelz opened this issue Jan 26, 2023 · 2 comments
Open

Comments

@amiregelz
Copy link

amiregelz commented Jan 26, 2023

I'm using useDocumentData in order to fetch a document and keep it updated.

When the hook is initialized, reading the doc is not permitted yet (due to a certain condition in the Firestore Security Rules not being met), therefor the read fails with FirebaseError: Missing or insufficient permissions.

However, after a few minutes there is a change in the database and the document can be read successfully.

If I refresh the page it works properly - otherwise the hook does not automatically update.

How can I fix that? I need it to automatically detect that there are permissions to read this document and keep me up to date with its data.

@amiregelz amiregelz changed the title React Firestore Hooks fail to update when read permission is not longer denied useDocumentData fails to update when read permission is not longer denied Jan 26, 2023
@ishowta
Copy link

ishowta commented Jan 31, 2023

I think that can be done by writing a query with the ID of the target document as a filter like below.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /tests/{id} {
      allow read: if resource.data.isPrivate == false;
      allow write: if true;
    }
  }
}
import {
  documentId,
  DocumentReference,
  query,
  setDoc,
  where,
} from "firebase/firestore";
import { useCollectionData } from "react-firebase-hooks/firestore";

export const Test = (docRef: DocumentReference) => {
  const [docs] = useCollectionData(
    query(
      docRef.parent,
      where(documentId(), "==", docRef.id),
      where(documentId(), "!=", "93OE3unhtzLf2buLXF3e" /* fake ID */), // hack from https://stackoverflow.com/q/67556515/7923918
      where("isPrivate", "==", false)
    )
  );
  const doc = docs?.[0];

  return (
    <>
      <p>{JSON.stringify(doc) ?? "loading"}</p>
      <button onClick={() => void setDoc(docRef, { isPrivate: false })}>
        update
      </button>
    </>
  );
};

@allynz
Copy link

allynz commented Jul 16, 2023

I think it's because of the useEffect dependency used in the code: link, which checks if the query has changed or not inside useDocument(query) before calling onSnapshot (I may be wrong though)

To overcome this issue, you can do something like this:

const query = firestoreChange ? <your query/document reference> : undefined/null;
const [doc, loading, error] = useDocumentData(query);

This will change your query depending on the firestore change and reload fetching
This assumes you have a way of identifying the change in frontend (eg: user sign sign in status)

Otherwise, you can use onSnapshot from firebase directly, and even make a custom hook

const unsubscribe = onSnapshot(
	documentReference, 
	(documentSnapshot) => {
		console.log(documentSnapshot.data());
		setValue(documentSnapshot.data());
		.... etc.
	})

You can read more about onSnapshot here: link

Hopefully this helps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants