You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React JS中如何动态渲染API数据并兼容三类数据场景

React API数据动态渲染兼容方案

核心问题梳理

现有代码存在3个核心问题导致场景不兼容:

  • 渲染判断逻辑完全写反:类组件的this.state属性始终存在,所以现有逻辑会永远展示兜底提示,永远不会走到列表渲染分支
  • 未做接口数据格式归一化:返回单条非数组数据时直接调用map方法会抛出类型错误
  • 缺失Redux返回数据监听逻辑:仅在componentDidMount触发了请求dispatch,没有将接口返回的结果更新到组件state,始终使用初始化的静态数据

修复方案

兼容逻辑说明

针对三类场景做统一处理:

  1. 无数据:将接口返回的空值、null、undefined统一处理为空数组,判断数组长度为0时展示兜底提示
  2. 单条非数组数据:将返回的对象包裹为长度为1的数组,可直接用map遍历
  3. 数组格式数据:直接使用返回结果即可

代码修改点

  • 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 11:09:03