I'm using the datatables.net library with React to generate nice-looking tables. To get a working example I hard-coded a variable dataSet and sent it as a prop to the component like this:
import React from "react"
import { TblFunc } from "./TblFunc"
export default function AppFunc() {
const dataSet = [
["site1", "device1"],
["site1", "device2"],
["site1", "device3"],
["site1", "device4"],
["site1", "device5"],
["site1", "device6"],
["site1", "device7"],
["site1", "device8"],
["site1", "device9"],
["site2", "device1"],
["site2", "device2"],
["site2", "device3"],
["site2", "device4"],
["site2", "device5"],
["site2", "device6"],
["site2", "device7"],
["site2", "device8"]
]
return (
<div>
<TblFunc data={dataSet} />
</div>
)
}
Now, instead of hard coding the dataSet variable, I want to generate it automatically by calling an API. I need to create an Array of Arrays object to mimic dataSet. The API returns an object like this:
{
"site1": [
"device-a01",
"device-a02",
"device-b01",
"device-b02"
],
"site2": [
"device-a01",
"device-a02",
"device-b01",
"device-b02",
"device-c01",
"device-c02"
]
}
Here is what I have tried:
import React from "react"
import { TblFunc } from "./TblFunc"
export default function AppFunc() {
const [tableData, setTableData] = React.useState([])
function buildTableData(site, device) {
const hubValue = []
hubValue.push(site)
hubValue.push(device)
return hubValue
}
React.useEffect(() => {
async function getData() {
const res = await fetch("https://api.com/api/devices/")
const data = await res.json()
Object.entries(data).forEach(([site, devices]) => {
const _tableData = devices.map(device => buildTableData(site, device))
console.log(_tableData)
setTableData(_tableData)
})
}
getData()
},[])
return (
<div>
{/* <TblFunc data={dataSet} /> // THIS WORKS */}
<TblFunc data={tableData} />
{JSON.stringify(tableData)}
</div>
)
}
When printing tableData to the screen I get this:
[["site1","device01"],["site1","device02"],["site1","device03"],["site1","device04"],["site1","device05"],["site1","device06"]["site1","device07"]]
I believe I have generated an Array of Array's object but for some reason when I pass it to the <TableFunc /> component it does not populate the table. This leads me to believe that tableData is not matching the dataSet object.
This is what <TableFunc /> looks like:
import React, { useEffect, useRef } from "react"
import $ from 'jquery'
export function TblFunc(props) {
$.DataTable = require('datatables.net')
const tableRef = useRef()
useEffect(() => {
// console.log(tableRef.current)
const table = $(tableRef.current).DataTable(
{
data: props.data,
columns: [
{ title: "Site"},
{ title: "Device"}
],
destroy: true // I think some clean up is happening here
}
)
// Extra step to do extra clean-up.
return function() {
console.log("Table destroyed")
table.destroy()
}
},[])
return (
<div>
<table className="display" width="100%" ref={ tableRef }></table>
</div>
)
}

forEachand setting the state at the end of each iteration, so you will only ever have the lastentryrefactored. You should instead refactor the fullObject.entriesarray, and then set state.entrybeing written totableDatahave i generated thetableDataobject correctly as an Array of Arrays? I can't even get the lastentryto display in the table.useEffect. A quick fix is to conditionally render the first render{!!tableData.length && <TblFunc data={tableData} />}, but you'll want to troubleshoot the actual rerender issue. (I would recommend using a React ready table library rather than one that relies on jQuery and direct DOM manipulation) Here's a quick sandboxuseEffectin theTblFunccomponent. Simply addprops.datato the dependency array.useEffect(() => { const table = $(tableRef.current).DataTable({ ...}, [props.data]);Updated sandbox