TypeError: Cannot read property 'data' of undefined - can't access Object "props" beyond certain level in Reactjs
TypeError: Cannot read property 'data' of undefined - can't access Object "props" beyond certain level in Reactjs
我正在 React
中通过 axios
使用 UseEffect
.
拨打 API
我们使用 useState
将响应设置为名为 data
的变量
const [data, setData] = useState({});
setData(response);
来自 NASA API 的响应,我们只得到一个对象(粘贴在下面)return为此调用。
因为我将响应命名为 "data" 并且它也有一个 "data" 键,如果我想记录 url,我知道我会输入 console.log(data.data.url)
这在我的 app.js
主函数中运行顺利。在我的 card.js
组件中,我可以成功记录 console.log(data)
和 console.log(data.data)
并且它给出的正是您所期望的,但是当我 console.log(data.data.url)
或 (data.data.title)
它变成了由于某种原因 undefined
,所以这会导致 JSX 的 return 函数出现大错误,网站无法加载:
TypeError: Cannot read property 'data' of undefined error.
我不认为我的命名有任何问题,因为它在对象的更高级别上工作正常,例如console.log(data.data)
有效,我眼前看到列出的下一级属性。
我真的是console.logging这个:
{console.log('FROM INSIDE THE RETURN')}
{console.log(props.data)} // works, displays object {}
{console.log(props.data.data)} //works, displays object one level lower
{console.log(props.data.data.url)} // type error. You name the property.
不用说这行不通,这是我完成作业的第一种方法:
<img src={props.data.data.url}/>
也就是说,在团队领导的帮助下,我们通过如下所示去除对象上游的顶层,使程序正常工作:
SetData(response.data)
// as opposed to
SetData(response)
// and then using
<img src={props.data.url}/>
所以我们不必触及 props 的底部,但为了清楚起见,我想知道为什么以及它对编译器有什么不同,特别是当它在 n-1 层上运行良好时,其中 n 是对象的层数。
我什至更改了其中一个数据变量的名称,因此 'data' 没有重复并且行为相同。
感谢您的帮助和见解!我非常感谢您可以分享的任何见解以及对我的问题的反馈。
这是我正在处理的对象。
{
data: {
copyright: "Bryan Goff",
date: "2020-03-18",
explanation: "What's happening behind...[truncated]...Florida, USA.",
hdurl: "https://apod.nasa.gov/apod/image/2003/AntiCrepRays_Goff_3072.jpg",
media_type: "image",
service_version: "v1",
title: "Anticrepuscular Rays over Florida",
url: "https://apod.nasa.gov/apod/image/2003/AntiCrepRays_Goff_960.jpg"
},
status: 200,
statusText: "OK",
headers: {
contenttype: "application/json"
},
config: {
url: "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY",
method: "get",
headers: {
Accept: "application/json, text/plain, */*"
},
transformRequest: [
null
],
transformResponse: [
null
],
timeout: 0,
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
maxContentLength: -1
},
request: {}
}
我的猜测是 api 调用需要一些时间,您正试图在 api 调用 returns 之前设置值。请尝试使用额外的 isLoading 状态来检查 api 是否仍在执行
import React from 'react';
const Component = () => {
const [isLoading,setIsLoading] = useState(true)
const [data, setData] = useState({});
useEffect(()=>{
setTimeout(()=>fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => response.json())
.then(json => {
setData(json)
setIsLoading(false)
}),1000)
},[0])
return(
isLoading ? 'Loading...' :
<div>
<h1>Hello {data.name}!</h1>
<p>Your username is {data.username}</p>
</div>
)
}
export default Component
This is indeed an interesting challenge.
Let's do step-by-step analysis and see if we'll agree:
// this initializes `data = {}` when the app first launches
const [data, setData] = useState({});
// Chances are, you are using this within the "useEffect"
// If so at that point, the above `data = response`
setData(response)
您很可能在 useEffect
.
内拨打 axios
NASA API 电话
那么,让我们缩小到 API 调用。
API 调用通常是异步的(非阻塞)。
换句话说,此数据获取过程不会阻止您的客户端执行其他 "activities"。话虽如此,让我们回到您的共享代码:
解释一:可能是我们在取数据的时候出现的
// works, because initially "data = {}"
{console.log(props.data)}
// works, displays object one level lower
{console.log(props.data.data)}
// Explaining this...
// APIs are often backend apps that query a database for actual data.
// This returned data is stored in "literals" (often arrays/lists/objects).
// type error. You name the property.
{console.log(props.data.data.url)}
// Based on the above explanation,
// despite the second `data` being an Object literal,
// "url" isn't yet defined since the API is still "querying" the database
解释2:可能是命名空间冲突
// If all is fine based on "explanation 1",
// then this could be a "namespace" conflict during compilation.
// At compilation, JS finds two variables named "data"
// 1. The initial data value,
data = {}
// 2. The returned data key,
{
data: {...},
}
// If we had a returned response as follows:
results = {
data: {...},
}
// we probably would have something like this working
{console.log(response.data.result.data.url)}
// And this might explains why these work...
{console.log(response.data.url)}
<img src={props.data.url}/>
记住,我们要处理的是固执的JavaScript。
这可能就是为什么现在越来越多的大型 Reactjs
项目涉及 TypeScript
.
我正在 React
中通过 axios
使用 UseEffect
.
拨打 API
我们使用 useState
data
的变量
const [data, setData] = useState({});
setData(response);
来自 NASA API 的响应,我们只得到一个对象(粘贴在下面)return为此调用。
因为我将响应命名为 "data" 并且它也有一个 "data" 键,如果我想记录 url,我知道我会输入 console.log(data.data.url)
这在我的 app.js
主函数中运行顺利。在我的 card.js
组件中,我可以成功记录 console.log(data)
和 console.log(data.data)
并且它给出的正是您所期望的,但是当我 console.log(data.data.url)
或 (data.data.title)
它变成了由于某种原因 undefined
,所以这会导致 JSX 的 return 函数出现大错误,网站无法加载:
TypeError: Cannot read property 'data' of undefined error.
我不认为我的命名有任何问题,因为它在对象的更高级别上工作正常,例如console.log(data.data)
有效,我眼前看到列出的下一级属性。
我真的是console.logging这个:
{console.log('FROM INSIDE THE RETURN')}
{console.log(props.data)} // works, displays object {}
{console.log(props.data.data)} //works, displays object one level lower
{console.log(props.data.data.url)} // type error. You name the property.
不用说这行不通,这是我完成作业的第一种方法:
<img src={props.data.data.url}/>
也就是说,在团队领导的帮助下,我们通过如下所示去除对象上游的顶层,使程序正常工作:
SetData(response.data)
// as opposed to
SetData(response)
// and then using
<img src={props.data.url}/>
所以我们不必触及 props 的底部,但为了清楚起见,我想知道为什么以及它对编译器有什么不同,特别是当它在 n-1 层上运行良好时,其中 n 是对象的层数。
我什至更改了其中一个数据变量的名称,因此 'data' 没有重复并且行为相同。
感谢您的帮助和见解!我非常感谢您可以分享的任何见解以及对我的问题的反馈。
这是我正在处理的对象。
{
data: {
copyright: "Bryan Goff",
date: "2020-03-18",
explanation: "What's happening behind...[truncated]...Florida, USA.",
hdurl: "https://apod.nasa.gov/apod/image/2003/AntiCrepRays_Goff_3072.jpg",
media_type: "image",
service_version: "v1",
title: "Anticrepuscular Rays over Florida",
url: "https://apod.nasa.gov/apod/image/2003/AntiCrepRays_Goff_960.jpg"
},
status: 200,
statusText: "OK",
headers: {
contenttype: "application/json"
},
config: {
url: "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY",
method: "get",
headers: {
Accept: "application/json, text/plain, */*"
},
transformRequest: [
null
],
transformResponse: [
null
],
timeout: 0,
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
maxContentLength: -1
},
request: {}
}
我的猜测是 api 调用需要一些时间,您正试图在 api 调用 returns 之前设置值。请尝试使用额外的 isLoading 状态来检查 api 是否仍在执行
import React from 'react';
const Component = () => {
const [isLoading,setIsLoading] = useState(true)
const [data, setData] = useState({});
useEffect(()=>{
setTimeout(()=>fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => response.json())
.then(json => {
setData(json)
setIsLoading(false)
}),1000)
},[0])
return(
isLoading ? 'Loading...' :
<div>
<h1>Hello {data.name}!</h1>
<p>Your username is {data.username}</p>
</div>
)
}
export default Component
This is indeed an interesting challenge.
Let's do step-by-step analysis and see if we'll agree:
// this initializes `data = {}` when the app first launches
const [data, setData] = useState({});
// Chances are, you are using this within the "useEffect"
// If so at that point, the above `data = response`
setData(response)
您很可能在 useEffect
.
内拨打 axios
NASA API 电话
那么,让我们缩小到 API 调用。
API 调用通常是异步的(非阻塞)。
换句话说,此数据获取过程不会阻止您的客户端执行其他 "activities"。话虽如此,让我们回到您的共享代码:
解释一:可能是我们在取数据的时候出现的
// works, because initially "data = {}"
{console.log(props.data)}
// works, displays object one level lower
{console.log(props.data.data)}
// Explaining this...
// APIs are often backend apps that query a database for actual data.
// This returned data is stored in "literals" (often arrays/lists/objects).
// type error. You name the property.
{console.log(props.data.data.url)}
// Based on the above explanation,
// despite the second `data` being an Object literal,
// "url" isn't yet defined since the API is still "querying" the database
解释2:可能是命名空间冲突
// If all is fine based on "explanation 1",
// then this could be a "namespace" conflict during compilation.
// At compilation, JS finds two variables named "data"
// 1. The initial data value,
data = {}
// 2. The returned data key,
{
data: {...},
}
// If we had a returned response as follows:
results = {
data: {...},
}
// we probably would have something like this working
{console.log(response.data.result.data.url)}
// And this might explains why these work...
{console.log(response.data.url)}
<img src={props.data.url}/>
记住,我们要处理的是固执的JavaScript。
这可能就是为什么现在越来越多的大型 Reactjs
项目涉及 TypeScript
.