[英]React: Uncaught TypeError: Cannot read properties of undefined
THIS QUESTION IS ALREADY SOLVED.这个问题已经解决了。 Scroll down or click here to view solutions
向下滚动或单击此处查看解决方案
I am trying to use React to extract a JSON data from my server and render it with two functions.我正在尝试使用 React 从我的服务器中提取 JSON 数据并使用两个函数渲染它。 But it seems that the two render functions cannot read the values in the json correctly.
但似乎这两个渲染函数无法正确读取 json 中的值。 I'm sure that my data server is working correctly.
我确定我的数据服务器工作正常。
Error log:错误日志:
Unhandled Runtime Error
Uncaught TypeError: Cannot read properties of undefined (reading 'title')
Source
http://localhost:8080/dist/App.js [:19:68]
TypeError: Cannot read properties of undefined (reading 'title')
at Question (http://localhost:8080/dist/App.js:19:68)
at renderWithHooks (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:16313:18)
at mountIndeterminateComponent (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:20077:13)
at beginWork (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:21590:16)
at beginWork$1 (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:27414:14)
at performUnitOfWork (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26548:12)
at workLoopSync (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26454:5)
at renderRootSync (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26422:7)
at performSyncWorkOnRoot (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26074:20)
at flushSyncCallbacks (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:12050:22)
App component:应用组件:
let prop
function App() {
const [item, setItems] = useState([])
useEffect(() => {
fetch('http://localhost:9090/')
.then((res) => res.json())
.then((resJson) => {
const data = JSON.parse(resJson)
setItems(data)
})
}, [])
prop = item
return (
<div>
<Question/>
<hr/>
</div>
)
}
Question component:问题组件:
function Question() {
return (
<div className={"question"}>
<h1>{ prop.question.title }</h1>
<p className={"info"}>Created by user: { prop.question.create_by }</p><br/>
<p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(prop.question.time)) }</p><br/>
<hr/>
<div dangerouslySetInnerHTML={{__html: prop.question.detail}}></div>
</div>
)
}
export default App;
The JSON data: JSON 数据:
{
"question": {
"title": "Question",
"create_by": "AZ",
"time": 1661394765044,
"detail": "<h4>info</h4>"
},
"answers": [
{
"create_by": "baa",
"time": 1661394765044,
"detail": "<h4>abc</h4>"
}
]
}
I think they are not pure functions, they are components, you cannot share global variables and that is not the way to pass data between components in React, the way to do it correctly is using a context or props, to pass through props I leave you an example of the following way, you should apply this in the other variables too, example:我认为它们不是纯函数,它们是组件,你不能共享全局变量,这不是在 React 中的组件之间传递数据的方式,正确的方法是使用上下文或道具,通过道具我离开您是以下方式的示例,您也应该将其应用于其他变量,例如:
function App() {
const [item, setItems] = useState([])
useEffect(() => {
fetch('http://localhost:9090/')
.then((res) => res.json())
.then((resJson) => {
const data = JSON.parse(resJson)
setItems(data)
})
}, [])
return (
<div>
<Question title={item.question.title}/>
<hr/>
</div>
)
}
function Question({title}) {
return (
<div className={"question"}>
<h1>{ title }</h1>
<p className={"info"}>Created by user: { prop.question.create_by }</p><br/>
<p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(prop.question.time)) }</p><br/>
<hr/>
<div dangerouslySetInnerHTML={{__html: prop.question.detail}}></div>
</div>
)
}
export default App;
First, in App
remove JSON.parse(resJson)
as it's already parsed by res.json()
.首先,在
App
中删除JSON.parse(resJson)
因为它已经被res.json()
解析了。 Use some loader while fetching the data as it happens asynchronously, and your component render first.在获取数据时使用一些加载器,因为它是异步发生的,并且您的组件首先呈现。 For that give nothing to
useState
as parameter so item
is undefined
at the beginning.为此,不要将
useState
作为参数,因此item
在开始时是undefined
的。
function App() {
const [item, setItems] = useState()
useEffect(() => {
fetch('http://localhost:9090/')
.then((res) => res.json())
.then((data) => {
setItems(data)
})
}, []);
if(!item) return <p>Fetching data...</p>
return (
<div>
<Question question = {item.question}/>
<hr/>
</div>
)
}
Second, you shouldn't be using global variables to render data in your components when using React, instead use props
and state
.其次,在使用 React 时,您不应该使用全局变量来渲染组件中的数据,而是使用
props
和state
。 To do so, change Question
component so it receives the data it needs as props
and notice it's passed in App
to it:为此,请更改
Question
组件,使其接收所需的数据作为props
,并注意它已在App
中传递给它:
function Question(props) {
return (
<div className={"question"}>
<h1>{ props.question.title }</h1>
<p className={"info"}>Created by user: { props.question.create_by }</p><br/>
<p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(props.question.time)) }</p><br/>
<hr/>
<div dangerouslySetInnerHTML={{__html: props.question.detail}}></div>
</div>
)
}
There are several problems on frontend and backend.前端和后端有几个问题。
Frontend:前端:
useState
and useEffect
to hendle fetched data.useState
和useEffect
来处理获取的数据。 This is my code:const [item, setItems] = useState()
useEffect(() => {
fetch('http://localhost:61780/')
.then((res) => res.json())
.then((data) => {
setItems(data)
})
}, []);
<level 1>?.<level 2>?.<level 3>
.<level 1>?.<level 2>?.<level 3>
。 DON'T DO THIS: <level 1>.<level 2>.<level 3>
.不要这样做:
<level 1>.<level 2>.<level 3>
。 This will throw out an exception: Cannot read... from type 'undefined'
这将抛出一个异常:
Cannot read... from type 'undefined'
Example code:示例代码:
import React, {useEffect, useState} from 'react';
import './extraUI.css'
function App() {
const [item, setItems] = useState()
useEffect(() => {
fetch('http://localhost:61780/')
.then((res) => res.json())
.then((data) => {
setItems(data)
})
}, []);
console.warn(item)
return (
<>
<Question props={item}/>
<hr/>
<Answer props={item}/>
</>
)
}
function Question({props}) {
return (
<div className={"question"}>
<h1>{ props?.question?.title }</h1>
<p className={"info"}>Created by user: { props?.question?.create_by }</p><br/>
<p className={"info"}>On { }</p><br/>
<hr/>
<div dangerouslySetInnerHTML={{__html: props?.question?.detail}}></div>
</div>
)
}
function Answer({props}) {
return (
props?.answers?.map((answer) => {
return (
<div className={"answer"}>
<h4 className={"info"}>Answer by: { answer?.create_by }</h4><br/>
<p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(answer?.time)) }</p><br/>
<hr/>
<div dangerouslySetInnerHTML={{__html: answer?.detail}}></div>
</div>
)
})
)
}
export default App;
Json data: Json 数据:
{
"question": {
"title": "Question",
"create_by": "AZ",
"time": 1661394765044,
"detail": "<h4>info</h4>"
},
"answers": [
{
"create_by": "baa",
"time": 1661394765044,
"detail": "<h4>abc</h4>"
}
]
}
Backend:后端:
Access-Control-Allow-Origin
, and it's value is your api url(or you can use *
if your api is a public one) It's like this: Access-Control-Allow-Origin: <url or *>
Access-Control-Allow-Origin
, and it's value is your api url(or you can use *
if your api is a public one) It's like this: Access-Control-Allow-Origin: <url or *>
If you don't do this, it will throw out an exception: CORS header 'Access-Control-Allow-Origin' missing
.如果你不这样做,它会抛出一个异常:
CORS header 'Access-Control-Allow-Origin' missing
。 I'm not sure if other js is like this.不知道其他js是不是这样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.