异步获取数据不重新渲染 ReactJS 数据表(或只是不显示新数据)

Posted

技术标签:

【中文标题】异步获取数据不重新渲染 ReactJS 数据表(或只是不显示新数据)【英文标题】:Async fetch of data not rerendering ReactJS datatable(or just not displaying new data) 【发布时间】:2019-10-14 05:24:30 【问题描述】:

这里的问题是,如果我的新数据是从我的后端(RestAPI)获取的,即使我调用了 this.setState,数据表也不会显示新数据,如果我记录新状态,获取的数据也会被记录到控制台,但未显示在我的数据表中。 当我在构造函数 this.state = xxx 中硬编码数据时,数据显示得很好。所以我认为这必须与一些重新渲染问题有关?我调试了几个小时,但我找不到问题。如果有人可以在这里帮助我,那就太好了:)

我阅读了很多关于不重新渲染和 React 组件生命周期的文章和帖子。作为进一步的信息,当我在返回值之前在 render 方法中记录状态时,它首先为 null(因为我初始化了状态),并且在第二次渲染之后,数据根据需要位于 this.state.rowData 中。但我根本不知道为什么它没有显示在数据表中。


    constructor(props) 
        super(props);
        this.state = 
            columnDefs: [
                headerName: "Dump Name", field: "dumpName", sortable: true, filter: true
            , 
                headerName: "Type", field: "type", sortable: true, filter: true
            , 
                headerName: "Size", field: "length", sortable: true, filter: true
            , 
                headerName: "Different CAN-IDs", field: "canIdCount", sortable: true, filter: true
            , 
                headerName: "Created At", field: "createdAt", sortable: true, filter: true
            ],
            rowData: null
        
    

    componentDidMount = async () => 
        let collectionData = [];
        await getSniffs().then(function (sniffdata) 
            sniffdata.map(async function (row) 
                collectionData.push(
                    dumpName: row,
                    length: await getMessageCount(row).then(function (res) 
                        return res[0].all;
                    ),
                    canIdCount: await getIdCountDistinct(row).then(function (res) 
                        return res[0].count;
                    ),
                    createdAt: await getFirstTimestamp(row).then(function (res) 
                        return res[0].firstTimestamp;
                    ),
                    type: "CAN Message"
                );
            );
        ).then(() => this.setState(
            rowData: collectionData
        ));
    ;

    render() 
        console.log(this.state);
        return (
            <div
                className="ag-theme-material"
                style=
                    height: '500px',
                    width: '1000px' 
            >
                <AgGridReact
                    // onRowClicked=this.onRowClicked.bind(this)
                    columnDefs=this.state.columnDefs
                    rowData=this.state.rowData>
                </AgGridReact>
            </div>
            // : <Loading/>;
    )


export default withRouter(SniffOverviewDatatable);

数据表只显示:没有要显示的行。 起初我认为这是正确的结果,但它应该得到更新并显示我检索到的数据。 日志准确显示所需的数据和数组结构。

感谢您的宝贵时间,我真的希望得到一些提示:)

编辑: 嘿嘿,我只是重写了 componentDidMount 函数,但它并没有改变任何东西,我害怕。数据被记录,但表没有得到更新:/

这是函数的新代码(使用async/await):

componentDidMount = async () => 
            let rowData = [];
            try 
                const sniffs = await getSniffs();
                sniffs.map(async function (row) 
                    const msgCount = await getMessageCount(row);
                    const idCount = await getIdCountDistinct(row);
                    const firstTimestamp = await getFirstTimestamp(row);

                    rowData.push(
                        dumpName: row,
                        length: msgCount[0].all,
                        canIdCount: idCount[0].count,
                        createdAt: firstTimestamp[0].firstTimestamp,
                        type: "CAN Message"
                    );
                );
             catch (e) 
                console.log(e);
            
            this.setState(
                rowData
            );
        ;

【问题讨论】:

【参考方案1】:

您是否已经尝试过将 setState 与回调函数和某种不可变库(例如 immutability-helper)一起使用?这将导致如下代码:

import update from 'immutability-helper';
...

this.setState(prevState => update(prevState, rowData: $set: collectionData);
...

【讨论】:

嘿 :) 感谢您的建议。我对此进行了测试并使用了这段代码 sn-p:this.setState(prevState =&gt; update(prevState, rowData: $set: rowData)); 恐怕我得到的结果和以前一样:ibb.co/S5Rj8Pq -> 渲染函数中 this.state.rowData 的 Console.log。【参考方案2】:

您好,如果有人看到这个问题,我只想提供我自己的答案:

    componentDidMount = async () => 
    let fetched = await getSniffs();

    let rowData = [];

    for (const row of fetched.data) 
        const msgCount = await getMessageCount(row);
        const idCount = await getIdCountDistinct(row);
        const firstTimestamp = await getFirstTimestamp(row);

        rowData.push(
            dumpName: row,
            length: msgCount.data[0].all,
            canIdCount: idCount.data[0].count,
            createdAt: new Date(firstTimestamp.data[0].firstTimestamp),
            type: "CAN Message"
        );
    

    this.setState(
        rowData
    );
;

现在可以正常工作了 :) 我还在上面的一个组件中迁移了这个方法,所以数据表只是通过 props 而不是通过 state 获取它的数据。 谢谢并关闭!

【讨论】:

以上是关于异步获取数据不重新渲染 ReactJS 数据表(或只是不显示新数据)的主要内容,如果未能解决你的问题,请参考以下文章

删除突变后不重新获取查询(Apollo Graphql & Nextjs)

解决vue开发时子组件数据和组件渲染的异步问题

如何在 ReactJS 中触发模型更改的重新渲染?

无法使用 ReactJs、Axios、Redux 渲染/显示从 api 获取的数据

vue先加载数据再渲染

在等待在 ReactJS 渲染中获取数据时显示加载微调器