React从Elasticsearch取数后刷新浏览器,报hits未定义错误如何解决?
解决React从Elasticsearch取数据时的"Cannot read properties of undefined (reading 'hits')"错误
问题根源
- 初始状态不匹配:你把
data的初始值设为数组[],但Elasticsearch返回的是包含hits和_shards的对象,渲染时直接访问data.hits会因为数组没有hits属性而报错。 - 异步数据未就绪:组件首次渲染和刷新后,API请求还没完成就开始渲染表格,此时
data还是初始值,访问深层属性必然抛出错误。
具体修复步骤
1. 初始化匹配返回结构的空状态
将data的初始值从数组改为符合Elasticsearch响应结构的空对象,确保渲染时不会因为属性不存在而崩溃:
const [data, setData] = useState({ hits: { hits: [] }, _shards: { failed: 0, skipped: 0, successful: 0, total: 0 } });
2. 使用可选链操作符避免深层属性报错
在渲染表格的每个数据项时,添加?.可选链操作符,确保即使某个层级未定义也不会抛出错误:
例如:
<td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._index, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.agent?.ephemeral_id, null, 2)}</pre></td>
3. (可选)添加加载状态提升体验
增加一个loading状态,在API请求未完成时显示加载提示,避免用户看到空白或错误内容:
const [loading, setLoading] = useState(true); // 在apiGet函数中修改: fetch(ur1, requestOptions) .then(response => response.json()) .then(result => { setData(result); setLoading(false); // 请求完成后关闭加载状态 }) .catch(error => { console.log('error', error); setLoading(false); }); // 渲染时判断: if (loading) { return <div>加载中...</div>; }
完整修改后的代码示例
import React, { useEffect, useState} from "react"; import './pages/table.css' function JsonDataDisplay() { // 初始化匹配Elasticsearch响应结构的空状态 const [data, setData] = useState({ hits: { hits: [] }, _shards: { failed: 0, skipped: 0, successful: 0, total: 0 } }); const [loading, setLoading] = useState(true); const apiGet = () => { var myHeaders = new Headers(); myHeaders.append("Authorization", "Basic ZWxhc3RpYzpydHoxMDRpWGtjcV85RjZUTCtMMA=="); var requestOptions = { method: 'GET', headers: myHeaders, redirect: 'follow' }; const ur1 = 'https://192.168.1.3:9200/clientesafewindows-logstash/_search' fetch(ur1, requestOptions) .then(response => response.json()) .then(result => { setData(result); setLoading(false); console.log(result); }) .catch(error => { console.log('error', error); setLoading(false); }); }; useEffect(() => { apiGet(); }, []); // 加载状态下显示提示 if (loading) { return <div>加载数据中...</div>; } return ( <div> <table className="table table-striped"> <thead> <tr> <th>Index</th> <th>Score</th> {/* Agent */} <th>Ephemeral_id</th> <th>Id</th> <th>Name</th> <th>Type</th> <th>Version</th> {/* Event */} <th>Original</th> {/* Host */} <th>Architecture</th> <th>Hostname</th> <th>Id</th> <th>IP</th> <th>MAC</th> <th>Name</th> {/* OS */} <th>Build</th> <th>Family</th> <th>Kernel</th> <th>Name</th> <th>Platform</th> <th>Type</th> <th>Version</th> {/* Input */} <th>Type</th> <th>Message</th> {/* Shards */} <th>Failed</th> <th>Skipped</th> <th>Success</th> <th>Total</th> </tr> </thead> <tbody> <tr> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._index, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._score, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.agent?.ephemeral_id, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.agent?.id, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.agent?.name)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.agent?.type, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.agent?.version, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.event?.original)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.architecture, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.hostname, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.id)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.ip?.[7], null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.mac, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.name, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.os?.build, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.os?.family)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.os?.kernel, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.os?.name, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.os?.platform, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.os?.type)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.host?.os?.version, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.input?.type, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?.hits?.hits?.[1]?._source?.message, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?._shards?.failed, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?._shards?.skipped, null, 2)}</pre></td> <td><pre>{JSON.stringify(data?._shards?.successful)}</pre></td> <td><pre>{JSON.stringify(data?._shards?.total, null, 2)}</pre></td> </tr> </tbody> </table> </div> ); } export default JsonDataDisplay;
内容的提问来源于stack exchange,提问作者khlinten demelash
相关产品推荐
相关产品推荐

