Я получаю это сообщение об ошибке TypeError: Cannot read properties of null (reading 'useState')
, когда использую свои пользовательские перехватчики внутри getStaticProps
для извлечения данных из хранилища firebase firebase. Кто-нибудь, пожалуйста, помогите мне с этим?
Challenges
код страницы:
import Card from "../components/reusable/Card"
import { useCollection } from "../hooks/useCollection"
const Challenges = ({ challenges }) => {
return (
<div className = "grid sm:grid-cols-2 lg:grid-cols-3 gap-6 justify-items-center mt-8">
{challenges.map((challenge) => {
return (
<Card key = {challenge.id} card = {challenge} />
)
})}
</div>
)
}
export default Challenges
export async function getStaticProps() {
const { documents, isLoading } = useCollection("challenges", null, null, [
"createdAt",
"desc",
])
return {
props: {
challenges: documents,
},
}
}
useCollection
код хука:
import { useEffect, useState } from "react"
import { collection, limit, onSnapshot, orderBy, query, where } from "firebase/firestore"
import { db } from "../firebase/config"
export const useCollection = (c, q, l, o) => {
const [documents, setDocuments] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
let ref = collection(db, c)
if (q) {
ref = query(ref, where(...q))
}
if (o) {
ref = query(ref, orderBy(...o))
}
if (l) {
ref = query(ref, limit(l))
}
const unsubscribe = onSnapshot(ref, (snapshot) => {
const results = []
snapshot.docs.forEach(
(doc) => {
results.push({ ...doc.data(), id: doc.id })
},
(error) => {
console.info(error)
setError("could not fetch the data")
}
)
// update state
setDocuments(results)
setIsLoading(false)
setError(null)
})
return () => unsubscribe()
}, [])
return { documents, error, isLoading }
}
Вы можете использовать useState
или любой хук только внутри компонента React, или пользовательский хук, как сказано в Rules of Hooks , и getStaticProps не является ни одним из двух. Кроме того, он запускается только во время сборки, поэтому не отправляется в браузер:
Если вы экспортируете функцию под названием
getStaticProps
(Генерация статического сайта) со страницы, Next.js предварительно отобразит эту страницу во время сборки, используя свойства, возвращаемыеgetStaticProps
.
Вы можете либо перенести выборку данных на клиент, либо избавиться от getStaticPros
, например:
import Card from "../components/reusable/Card";
import { useCollection } from "../hooks/useCollection";
const Challenges = () => {
const {
documents: challenges,
isLoading,
error,
} = useCollection("challenges", null, null, ["createdAt", "desc"]);
if (isLoading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error happend</p>;
}
return (
<div className = "grid sm:grid-cols-2 lg:grid-cols-3 gap-6 justify-items-center mt-8">
{challenges.map((challenge) => {
return <Card key = {challenge.id} card = {challenge} />;
})}
</div>
);
};
export default Challenges;
Или преобразовать useCollection
в обычную асинхронную функцию без каких-либо хуков и использовать ее внутри getStaticProps
. Но не похоже, что это то, что вы хотите, так как вы создаете подписку на клиенте и все.
Хорошо, я вижу. Держите меня в курсе, решена ли тема или нет :)
Да, теперь это решено! Вместо того, чтобы вызывать хук внутри getStaticProps, я напрямую извлекаю данные из него.
Для сбора вызовов я планирую удалить подписку с клиента. Итак, я думаю, что я должен получить данные внутри этого хука и вернуть их вместо обновления переменной состояния. Затем получите доступ к этим данным внутри файла
getStaticProps
.