У меня есть документ Firestore users, который выглядит примерно так:
{
currentCompanyId: "123",
displayName: "Mary Jane"
}
И документ Firestore websites, который выглядит примерно так:
{
companyId: "123",
homePageUrl: "https://www.google.com/"
}
Теперь я пытаюсь использовать оболочку VueUse useFirestore() для отображения websites документа.
Для этого я ссылаюсь на свойство currentCompanyId документа users внутри ограничения запроса where следующим образом:
<template>
<div>
{{ websites?.[0] }}
</div>
</template>
<script setup lang = "ts">
import { useAuth } from '@vueuse/firebase/useAuth';
import { useFirestore } from '@vueuse/firebase/useFirestore';
import { collection, doc, query, where } from 'firebase/firestore';
import { auth, db } from 'src/config/firebase';
import { User } from 'src/types';
import { computed } from 'vue';
const { user: authUser } = useAuth(auth);
const userDocRef = doc(db, `users/${authUser.value?.uid}`);
const user = useFirestore<User>(userDocRef);
const websiteQuery = computed(() =>
query(
collection(db, 'websites'),
where('companyId', '==', user.value?.currentCompanyId) // This produces an error
// where('companyId', '==', '123') // This works, but is not practical
)
);
const websites = useFirestore(websiteQuery);
</script>
Жесткое кодирование companyId значения 123 работает.
Но всякий раз, когда я использую user.value?.currentCompanyId внутри вычисляемой ссылки, возникает ошибка, говорящая следующее:
TypeError: правая часть "in" должна быть объектом, полученным нулем



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Попробуйте передать QueryConstraint только тогда, когда значение определено следующим образом:
const websiteQuery = computed(() => {
const queryContraints: any = [];
const currentCompanyId = user.value?.currentCompanyId;
if (currentCompanyId) queryContraints.push(where("companyId", "= = ", currentCompanyId));
return query(
collection(db, 'websites'),
...queryContraints
)
});
Однако это вернет все документы, если вы не укажете ограничение where(), поэтому, возможно, попробуйте запустить запрос только тогда, когда он определен, то есть после загрузки состояния аутентификации. onAuthStateChanged() здесь может пригодиться.
@TinyTiger, когда вы используете литералы шаблонов, результатом будет "undefined" (в виде строки), так что это допустимое значение. Он будет искать документы, где companyId равно "undefined" (строка). Но undefined не является допустимым значением.
Я понял.
Проблема была в том, что user.value?.currentCompanyId изначально null.
Вот снова сообщение об ошибке:
TypeError: правая часть "in" должна быть объектом, полученным нулем
По сути, это говорит о том, что правая часть ограничения запроса Where должна быть объектом, но она стала нулевой.
Обертывание запроса в ссылку computed в конечном итоге изменит значение с null на что-то другое при его обновлении. Но изначально это null. И в этом причина ошибки.
Чтобы решить эту проблему, вы можете установить некоторые начальные свойства user в useFirestore. Таким образом, ограничение запроса Where изначально будет использовать это ненулевое значение. Даже пустая строка будет в порядке. Вы можете использовать все, что не является null.
Вот полный код:
<template>
<div>
{{ websites?.[0] }}
</div>
</template>
<script setup lang = "ts">
import { useAuth } from '@vueuse/firebase/useAuth';
import { useFirestore } from '@vueuse/firebase/useFirestore';
import { collection, doc, query, where } from 'firebase/firestore';
import { auth, db } from 'src/config/firebase';
import { User } from 'src/types';
import { computed } from 'vue';
const { user: authUser } = useAuth(auth);
const userDocRef = doc(db, `users/${authUser.value?.uid}`);
const user = useFirestore<User>(userDocRef, { currentCompanyId: '' }); // <-- See change here
const websiteQuery = computed(() =>
query(
collection(db, 'websites'),
where('companyId', '==', user.value?.currentCompanyId)
)
);
const websites = useFirestore(websiteQuery);
</script>
Спасибо, это работает, и я уже гарантирую, что состояние аутентификации загружается при запуске приложения, так что это не проблема. Я также заметил, что я могу использовать шаблонные литералы (обратные галочки) для такого значения
`${user.value?.currentCompanyId}`, и это работает. Можете ли вы пролить свет на то, почему это работает? Я думал, что литерал пустого шаблона будетundefinedи, следовательно, также выдаст ошибку, но этого не происходит.