javascript - 如何使用 ReactJS 显示来自 JSON 对象的数据?
问题描述
新程序员在这里学习 ReactJS。我有一些代码使用 axios 发出 HTTP 请求以从本地文件获取 XMLData。然后在响应中,我使用 xml-js 将 XML 数据转换为 JSON 对象。然后,我将其jsonObj
保存到使用setState()
.
我有一个renderTableRows()
应该返回 JSX 以在浏览器上显示我的 JSON 数据的函数。我解构了状态并尝试从中控制台日志,renderTableRows()
但是当我尝试访问时,users.result.body
我得到了
“TypeError:无法读取未定义的属性‘body’”。
当我从then()
内部执行此操作时,componentDidMount()
我能够访问数据。我还在代码底部包含了我正在阅读的数据的摘录。
我想遍历map()
所有行数组属性。任何帮助,将不胜感激。
class Table extends Component {
constructor(props) {
super(props)
this.state = {
users: []
}
}
async componentDidMount() {
axios.get(XMLData, {
"Content-Type": "application/xml; charset=utf-8"
})
.then((response) => {
var jsonObj = convert.xml2js(response.data,{compact:true, spaces: 4});
this.setState({users:jsonObj});
//console.log(this.state.users.result.body.row[0].col[0]);
});
}
renderTableHeader = () => {
return <th>
<td>Division Full Path</td>
<td>Billable Hours</td>
<td>Vacation Hours Only</td>
<td>Total Hours</td>
</th>
}
renderTableRows = () => {
const {users} = this.state
console.log(users.result.body);
return <h1>Hello from table rows</h1>
}
render() {
//const { users } = this.state
return <table>
<thead>
<tr>
{this.renderTableHeader()}
</tr>
</thead>
<tbody>
<tr>
{this.renderTableRows()}
</tr>
</tbody>
</table>
}
"header": {
"col": [
{
"label": {
"_text": "Counter Source Date"
}
},
{
"label": {
"_text": "Employee Id"
}
},
{
"label": {
"_text": "Counter Hours"
}
},
{
"label": {
"_text": " Division Full Path"
}
},
{
"label": {
"_text": " Projects/Equip/Vessels\nBillable"
}
},
{
"label": {
"_text": "Counter Name"
}
}
]
}
"body": {
"row": [
{
"col": [
{
"_text": "01/01/2021"
},
{
"_text": "2183"
},
{
"_text": "8.00"
},
{
"_text": "01 - Fort Lauderdale/Salvage"
},
{
"_text": "No"
},
{
"_text": "Holiday"
}
]
}
]
}
解决方案
问题
初始状态与在 中的访问方式不匹配renderTableRows
。
this.state = {
users: []
}
这this.state.users
是一个数组,所以this.state.users.result
是未定义的。这很好,直到您尝试访问body
属性并TypeError: Cannot read property 'body' of undefined
引发错误。
一个解法
您可以从有效的初始状态开始:
this.state = {
users: {
result: {}
}
}
或者使用一堆保护子句renderTableRows
:
renderTableRows = () => {
const { users } = this.state
console.log(users.result && users.result.body);
return <h1>Hello from table rows</h1>
}
或使用可选链:
renderTableRows = () => {
const { users } = this.state
console.log(users.result?.body);
return <h1>Hello from table rows</h1>
}
由于您提到想要通过行进行映射,所以第一个选项不是您想要的。如果渲染行,它将类似于:
renderTableRows = () => {
const {users} = this.state
return users.map(user => (....))
}
更新
我建议将你的状态设置为jsonObj.result
属性,这样你就不需要在result
每次渲染时访问属性,它只是缩短了访问。映射this.state.users.headerColumns
到标题列并映射this.state.rows
到每一行,另外还映射行列。
class Table extends Component {
constructor(props) {
super(props);
this.state = {
users: {
headerColumns: [],
rows: [],
}
};
}
async componentDidMount() {
axios
.get(XMLData, {
"Content-Type": "application/xml; charset=utf-8"
})
.then((response) => {
var jsonObj = convert.xml2js(response.data, {
compact: true,
spaces: 4
});
this.setState({ users: {
headerColumns: jsonObj.header.col,
rows: jsonObj.body.row
} });
});
}
renderTableHeader = () => {
const { users: { headerColumns } } = this.state;
return (
<th>
{headerColumns.map(col => (
<td key={col.label._text}>{col.label._text}</td>
))}
<td>Total Hours</td>
</th>
);
};
renderTableRows = () => {
const { users: { rows } } = this.state;
return rows.map((row, index) => {
let computedTotal;
return (
<tr key={index}>
{row.col.map((value, index) => {
// compute time total from row data
return (
<td key={index}>{value}</td>
);
})}
<td>{computedTotal}</td>
</tr>
)});
};
render() {
return (
<table>
<thead>
<tr>{this.renderTableHeader()}</tr>
</thead>
<tbody>
{this.renderTableRows()}
</tbody>
</table>
);
}
}
推荐阅读
- flutter - 放大图像并将图像居中到卡片小部件和剪辑溢出
- python - TypeError:张量不可散列
- python - 通知用户 Dash 中的无效输入
- python-3.x - 如何从数组创建数据框
- heritrix - 从 Heritrix 网络爬虫获取 URL 图
- python - 如何使用 Python 代码移动文件
- python - 应用程序与 buildpack Django heroku 不兼容
- python - Python Pandas 插值:在缺失的日期范围内重新分配值
- rest - 如何防止攻击者使用我的密码重置机制向炸弹人发送电子邮件?
- c - Can't figure out what's wrong with my code for a HackerRank problem in C