为什么即使使用 Firebase Realtime DB 在 React 中返回了一个值,我也会得到“未定义”的结果?
我正在使用 Firebase 开发我的小型 React 驱动 Web 应用。我设置了 Firebase 配置,并向 Firebase 实时数据库添加了一些数据。我在 Firebase 中的数据设置如下:
{
"matches" : {
"ace34187-c7f2-41e7-a7f2-f097963cddc5" : {
"questions" : [ {
"answers" : [ {
"answer" : "4",
"isCorrect" : true
}, {
"answer" : "2",
"isCorrect" : false
}, {
"answer" : "12",
"isCorrect" : false
}, {
"answer" : "6",
"isCorrect" : false
} ],
"question" : "What is two plus two?",
"type" : "multi-choice-answer"
} ]
}
},
"sessions" : {
"9d82c839-b3e1-474a-a084-61141293efa3" : {
"code" : "1234",
"rootMatch" : "ace34187-c7f2-41e7-a7f2-f097963cddc5",
"teams" : {
"9d82c839-b3e1-474a-a084-61141293efa3" : {
"emoji" : "1f34f",
"name" : "Apples",
"score" : 0,
"strikes" : 0
},
"dc550e48-5bc5-4e6c-bfef-c6626cf6d94b" : {
"emoji" : "1f4a9",
"name" : "Pickles",
"score" : 0,
"strikes" : 0
}
}
}
}
}
我为
match
设置了一个状态,该状态使用空对象初始化:
const [match, setMatch] = useState({});
每个
match
都有一个问题数组,这些问题具有相应的答案和类型。我正在使用以下函数从 Firebase 实时数据库获取这些
match
:
const getMatch = () => {
return onValue(
ref(db, "/matches/ace34187-c7f2-41e7-a7f2-f097963cddc5"),
(snapshot) => {
console.log(snapshot.val());
setMatch(snapshot.val());
},
{
onlyOnce: true,
}
);
};
然后通过
useEffect
React Hook 调用此函数,其依赖项列表为空,如以下代码所示:
useEffect(() => {
getMatch();
}, []);
接下来,我想获取
match
数据并将其放入我的 JSX 代码中,类似于此:
return (
<div className="App">
<h1>{match.questions[0].question}</h1>
<AnswerBox question={match.questions[0]} />
</div>
);
当我设置所有这些代码时,我最终出现错误:
TypeError: match.questions is undefined
我将
match
记录到控制台以查看它是否有任何值或返回为
undefined
,这就是我返回的内容:
Object { }
Object { }
Object { questions: (1) […] }
​
questions: Array [ {…} ]
​​
0: Object { answers: (4) […], question: "What is two plus two?", type: "multi-choice-answer" }
​​
length: 1
​​
<prototype>: Array []
​
<prototype>: Object { … }
为什么
match
返回两个空对象,然后返回一个带有值的对象。另外,如果 match 不是
undefined
,为什么我会收到类型错误。
match.questions
在您调用 firebase 完成之前是未定义的。在此之前,
match
是一个空对象,如使用
useState
设置的。
您可以在 JSX 中使用可选链来避免这些错误。
return (
<div className="App">
<h1>{match.questions?[0].question}</h1>
<AnswerBox question={match.questions?[0]} />
</div>
);
match
的初始状态为
{},因此
match.questions
确实为
undefined
。尝试将初始状态更改为:
const [match, setMatch] = useState({ questions: [] })
另外尝试删除
return
,因为
onValue
无论如何都会返回一个取消订阅侦听器的函数:
const getMatch = () => {
onValue(ref(db, "/matches/ace34187-c7f2-41e7-a7f2-f097963cddc5"), (snapshot) => {
console.log(snapshot.val());
setMatch(snapshot.val());
}, {
onlyOnce: true,
});
};