React JS中如何动态渲染API数据并兼容三类数据场景
React API数据动态渲染兼容方案
核心问题梳理
现有代码存在3个核心问题导致场景不兼容:
- 渲染判断逻辑完全写反:类组件的
this.state属性始终存在,所以现有逻辑会永远展示兜底提示,永远不会走到列表渲染分支 - 未做接口数据格式归一化:返回单条非数组数据时直接调用
map方法会抛出类型错误 - 缺失Redux返回数据监听逻辑:仅在
componentDidMount触发了请求dispatch,没有将接口返回的结果更新到组件state,始终使用初始化的静态数据
修复方案
兼容逻辑说明
针对三类场景做统一处理:
- 无数据:将接口返回的空值、null、undefined统一处理为空数组,判断数组长度为0时展示兜底提示
- 单条非数组数据:将返回的对象包裹为长度为1的数组,可直接用map遍历
- 数组格式数据:直接使用返回结果即可
代码修改点
- 用
react-redux的connect高阶组件将Redux中存储的接口返回数据映射到组件props - 新增
formatData工具方法统一处理返回数据格式 - 修正render分支判断逻辑,先判断数组长度再渲染对应内容
- 列表项key改用唯一id替代index,避免渲染异常
- 修复原代码中所有展示字段错误复用
details.name.Value的问题
完整修正代码
import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { Container, Collapsible } from '你的组件实际引入路径'; import { allForsat } from '你的action实际引入路径'; class ForsatView extends React.Component { constructor(props) { super(props); // 初始化数据统一转成数组格式 this.state = { data: this.formatData([ { id: this.props.auth.FormInfoList.FormInfo.CrmId, name: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[2], repairsReport: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[4], serialNumber: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[8], model: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[17], face: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[7], situation: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[1], fistly: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[0], transport: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[16], reciveDate: this.props.auth.FormInfoList.FormInfo.ExtendedProperties.BaseCrmObjectExtendedPropertyInfo[15], }, ]), } } // 统一格式化数据为数组,兼容所有返回场景 formatData = (rawData) => { if (!rawData) return []; if (Array.isArray(rawData)) return rawData; return [rawData]; } componentDidMount() { this.props.dispatch(allForsat()) } // 监听接口返回数据变化,更新state componentDidUpdate(prevProps) { // forsatList替换为你项目Redux中存储接口返回数据的对应字段 if (prevProps.forsatList !== this.props.forsatList) { this.setState({ data: this.formatData(this.props.forsatList) }) } } static propTypes = { isAuthenticated: PropTypes.bool, auth: PropTypes.object.isRequired, forsatList: PropTypes.oneOfType([PropTypes.array, PropTypes.object]), dispatch: PropTypes.func.isRequired, } render() { const { data } = this.state; return ( <Container> <div className="panel-content"> {/* 修正判断逻辑:数组长度为0展示兜底提示 */} {data.length === 0 ? <div className="mt-5">No service</div> : <div className="mt-4 tab-profile-collaps text-right"> {data.map((details) => <Collapsible key={details.id} trigger={details.name?.Value ?? ''}> <div className="row"> <div className={"col-lg-6 col-12"}> <div className="forsat-detial-wrapper"> <div className={"title-tech-advice"}> <h5> Report </h5> <p> {details.name?.Value ?? ''} </p> </div> </div> </div> <div className={"col-lg-6 col-12"}> <div className="forsat-detial-wrapper"> <div className="forsat-detial-wrapper-boxes"> <p>Date</p><span className="d-flex">{details.reciveDate?.Value ?? ''}</span> <p className="mt-3">Name</p><span className="d-flex">{details.name?.Value ?? ''}</span> <p className="mt-3">SerialNymber</p><span className="d-flex">{details.serialNumber?.Value ?? ''}</span> <p className="mt-3">Model</p><span className="d-flex">{details.model?.Value ?? ''}</span> <p className="mt-3">Details</p><span className="d-flex">{details.situation?.Value ?? ''}</span> </div> </div> </div> </div> </Collapsible> )} </div> } </div> </Container> ); } } // 将Redux数据映射到组件props,字段路径替换为你项目的实际配置 const mapStateToProps = (state) => ({ forsatList: state.forsat.forsatList, auth: state.auth, }) export default withRouter(connect(mapStateToProps)(ForsatView))
注:如果你的项目不支持可选链
?.和空值合并运算符??,可以替换为普通的逻辑与判断,避免undefined报错。
内容的提问来源于stack exchange,提问作者Sajjad Shiasi
相关产品推荐
相关产品推荐

