为啥我的 JSON 响应在 forEach 上崩溃? TypeError 未定义
Posted
技术标签:
【中文标题】为啥我的 JSON 响应在 forEach 上崩溃? TypeError 未定义【英文标题】:Why does my JSON response crash on forEach? With TypeError undefined为什么我的 JSON 响应在 forEach 上崩溃? TypeError 未定义 【发布时间】:2021-08-16 09:44:03 【问题描述】:我设置了一个 Cloud Firebase 数据库,我正在向它发出 fetch 请求,但是当我尝试遍历返回对象中的数组时,我得到 TypeError: Cannot read property 'forEach' of undefined
,但我不确定为什么......我看到了一些帖子建议 JSON.parse res 但它没有改变输出..
import React, useState, useEffect from "react";
import axios from "axios";
const Submissions = () =>
const [state, setState] = useState();
useEffect(() =>
axios
.get("/submissions")
.then((res) =>
setState(
submissions: res.data,
);
)
.catch((err) =>
console.error(err);
);
// eslint-disable-next-line
, []);
return (
<div style= paddingTop: "3rem" >
<h1>Submissions</h1>
state.submissions !== null &&
state.submissions.forEach((element) =>
<p>element.patientName</p>;
)
</div>
);
;
export default Submissions;
如果我返回以下内容而不是迭代数组:
<p>JSON.stringify(state)</p>
但我确实得到了我期望的虚拟数据响应:
"submissions":["submissionId":"NxkofnOyiZSjpBa918it","patientName":"Bobby Hill","onsetDate":"2021-05-28T01:41:44.368Z","immuno":true,"highrisk":false,"symptoms":true,"collectionDate":"2021-05-28T01:41:44.368Z","createdAt":"2021-05-28T01:42:00.042Z","submissionId":"PuyDsvIlNC5Mi1h5u7b5","patientName":"Theo","onsetDate":"2021-05-28T01:20:06.275Z","immuno":false,"highrisk":false,"symptoms":false,"collectionDate":"2021-05-28T01:20:06.275Z","createdAt":"2021-05-28T01:20:06.275Z"]
【问题讨论】:
你可以去掉state.submissions!==null
并用 state.submissions?.map
替换 state.submissions.forEach
。其中?
称为optional chaining 运算符。 .forEach
不返回数组,但您需要这样做,这就是我们使用 .map
的原因。还要在 <p>element.patientName</p>
之前添加 return
前缀。
【参考方案1】:
最初state.submissions
将是undefined
,而undefined !== null
是true,因为它们不是strictly equal。
state.submissions !== null
=> undefined !== null
=> true
因为即使没有数据,state.submissions !== null
的计算结果仍为 true,因此您最终尝试在 undefined
上调用 forEach
。
要解决这个问题,您可以
做一个非身份equality comparison:state.submissions != null
,或者
只需通过 state.submissions && ( ... )
测试truthiness
除了 API 响应中的属性之外,您还将状态设置为具有自己的提交属性的对象。
因此,具有 submits 属性的数据位于组件状态自己的 submits 属性下。
有效:setState( submissions: submissions: […]
因此,您必须访问 state.submissions.submissions
才能访问数组。
改为直接设置响应:setState(res.data)
您将遇到的下一个问题是您的 forEach 中的任何内容都不会呈现,因为该函数不会返回任何内容。将其更改为 map 并在每次迭代时返回标记:
state.submissions &&
state.submissions.map((element) =>
return <p>element.patientName</p>;
)
如果您的环境支持(或 polyfills)optional chaining,您可以通过完全消除条件来进一步简化此操作,而我们使用箭头函数的 implicit return:
state.submissions?.map?.((element) => <p>element.patientName</p>)
【讨论】:
我尝试使用 state.submissions && 来测试真实性,但也让我感到困惑 您还将状态设置为具有独立于 API 响应的自己的submissions
属性的对象,因此具有提交属性的数据位于您所在状态的提交属性下。有效:setState( submissions: submissions: […] . So you’d have to access state.submissions.submissions to get to the array. Set the response directly instead:
setState(res.data)` 答案已更新。
我尝试使用带返回的地图,它终于奏效了! ``` state.submissions && state.submissions.map((element, i) => console.log(element); return import React, useState, useEffect from "react";
import axios from "axios";
const Submissions = () =>
const [submissions, setSubmissions] = useState([]);
useEffect(() =>
axios
.get("/submissions")
.then((res) =>
setSubmissions(res.data);
)
.catch((err) =>
console.error(err);
);
// eslint-disable-next-line
, []);
return (
<div style= paddingTop: "3rem" >
<h1>Submissions</h1>
submissions.length &&
submissions.forEach((element) =>
<p>element.patientName</p>;
)
</div>
);
;
编辑:我推荐上面的代码。我假设您在数据之间分离状态并对此给出了答案。以下答案不适用于您的情况。不管怎样,我拿着它以防有人需要它。
问题是你的渲染部分是在useEffect之前执行的。所以在第一次渲染中,你的状态是。您必须通过将状态设置为
[]
而不是 .
Object
来处理这种情况。Object
没有 forEach
。
【讨论】:
setSubmissions(res.data)
将状态设置为具有提交属性的对象。如果你想走这条路,你想把它改成setSubmissions(res.data.submissions);
以上是关于为啥我的 JSON 响应在 forEach 上崩溃? TypeError 未定义的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 foreach 循环与 users.json 文件中的键不匹配
仍然使用同源策略 为啥 JSON 响应在 https 链接上使用 jquery ajax 是空白的?