开发者问题收集

为什么即使使用 Firebase Realtime DB 在 React 中返回了一个值,我也会得到“未定义”的结果?

2021-09-12
217

我正在使用 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 ,为什么我会收到类型错误。

2个回答

match.questions 在您调用 firebase 完成之前是未定义的。在此之前, match 是一个空对象,如使用 useState 设置的。

您可以在 JSX 中使用可选链来避免这些错误。

return (
    <div className="App">
      <h1>{match.questions?[0].question}</h1>
      <AnswerBox question={match.questions?[0]} />
    </div>
);
MaxO
2021-09-12

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,
  });
};
Dharmaraj
2021-09-12