React:未捕获的 TypeError:无法读取未定义的属性
此问题已解决。向下滚动或 单击此处 查看解决方案
我尝试使用 React 从我的服务器提取 JSON 数据并使用两个函数渲染它。但似乎两个渲染函数无法正确读取 json 中的值。 我确定我的数据服务器正常工作。
错误日志:
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)
应用组件:
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>
)
}
问题组件:
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;
JSON 数据:
{
"question": {
"title": "Question",
"create_by": "AZ",
"time": 1661394765044,
"detail": "<h4>info</h4>"
},
"answers": [
{
"create_by": "baa",
"time": 1661394765044,
"detail": "<h4>abc</h4>"
}
]
}
我认为它们不是纯函数,它们是组件,你不能共享全局变量,这不是在 React 中在组件之间传递数据的方式,正确的方法是使用上下文或 props,通过 props 传递数据我给你留下了以下方式的示例,你也应该在其他变量中应用它,例如:
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;
首先,在
App
中删除
JSON.parse(resJson)
,因为它已被
res.json()
解析。在获取数据时使用一些加载器,因为它是异步发生的,并且您的组件首先呈现。为此,不要将任何内容提供给
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>
)
}
其次,使用 React 时,您不应该使用全局变量在组件中呈现数据,而是使用
props
和
state
。为此,更改
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>
)
}
编辑:我终于解决了这个问题。希望它能帮助你。
前端和后端都存在一些问题。
前端:
-
我使用
useState
和useEffect
来处理获取的数据。 这是我的代码:
const [item, setItems] = useState()
useEffect(() => {
fetch('http://localhost:61780/')
.then((res) => res.json())
.then((data) => {
setItems(data)
})
}, []);
-
在读取 json 数据时,请执行以下操作:
<level 1>?.<level 2>?.<level 3>
。
不要这样做:
<level 1>.<level 2>.<level 3>
。这会抛出一个异常:
Cannot read ... from type 'undefined'
示例代码:
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数据:
{
"question": {
"title": "Question",
"create_by": "AZ",
"time": 1661394765044,
"detail": "<h4>info</h4>"
},
"answers": [
{
"create_by": "baa",
"time": 1661394765044,
"detail": "<h4>abc</h4>"
}
]
}
Backend:
-
你需要在服务器响应中添加一个header:
Access-Control-Allow-Origin
,它的值是你的api url(或者如果你的api是公共的,你可以使用*
) 就像这样:Access-Control-Allow-Origin: <url or *>
如果你不这样做,它会抛出一个异常:
CORS header 'Access-Control-Allow-Origin' missing
。我不确定其他js是否是这样的。