0
votes

I have a Table from react-bootstrap that displays a list of devices with several columns. I want to change this so you can reorder by the columns so I switched to BootstrapTable from react-bootstrap-table-next. But my problem is that changing the state of the Component doesn't cause the table to update - this only happens if I click on a column to reorder the table.

The code is written to create the devices_table and save it to state then call an API to get the device version and add that to the state, causing the component to redraw. But when render() is called again the additional data isn't added to the table.

I've created a working example at https://codesandbox.io/s/react-bootstrap-table-next-new-data-problem-5w0op

import React, { Component } from 'react'
import BootstrapTable from 'react-bootstrap-table-next'

class DeviceTable extends Component {

    constructor(props) {
        super(props)

        this.state = {
            devices_table: {}
        }
    }

    componentDidUpdate(prevProps) {
        if (prevProps.devices !== this.props.devices) {
            let devices_table = this.props.devices.map(this.myFunction);
            this.setState({
                devices_table: devices_table
            })
        }
    }

    myFunction = (value, index, array) => {
        let device = {};

        device.device = value;
        device.index = index + 1;
        device.version = '';

        apiGetDeviceVersion(value.identifier)
            .then((res, deviceId = value.identifier) => {
                let devices_table = this.state.devices_table;
                let objIndex = devices_table.findIndex(d => d.device.identifier === deviceId)
                devices_table[objIndex].version = res.valueReported;
                this.setState({
                    devices_table: devices_table
                })
            })
            .catch(e => {
                console.log(e)
            })

        return device;
    }

    render() {
        const devices = this.state.devices_table;
        if (isEmpty(devices)) {
            return (<div></div>)
        }
        let columns = [
            {
                text: "#",
                dataField: "index",
                sort: true
            },
            {
                text: "ID",
                dataField: "device.identifier",
                sort: true
            },
            {
                text: "Name",
                dataField: "device.name",
                sort: true
            },
            {
                text: "Status",
                dataField: "device.status",
                sort: true
            },
            {
                text: "Version",
                dataField: "version",
                sort: true
            }
        ];

        return (
            <div>
                <BootstrapTable keyField={"device.identifier"} data={devices} columns={columns}></BootstrapTable>
            </div>
        )
    }
}

export default DeviceTable
1

1 Answers

0
votes
componentDidUpdate(prevProps) {
   if (prevProps.devices !== this.props.devices) {
            *let devices_table* = this.props.devices.map(this.myFunction);
            this.setState({
                devices_table: devices_table
            })
        }
}

It may happen due to response is working as asynchronous function(because of API). Thus, you have to wait for the response to make it available, otherwise "devices_table" remains empty or undefined and leads to no data visualization.