My application pulls data from an API and presents this data to the user. My table from react-table is just one component that uses this data and so I store the API response in Context. I am able to make this context data available to the table component, and I have a test to make sure the data is available before setting value / rendering, but for some reason the table does not appear.
There is a stackblitz at https://stackblitz.com/edit/react-jvmryf and you can see an example of the behaviour at https://react-jvmryf.stackblitz.io/jinky32/own
The code for my component is below, any help would be much appreciated, I've been fighting this for ages now with no joy! I assume this is because the context data is not set by the time my if statement checks, but how can I wait for it to be set?
import React, { useMemo, useState, useEffect, useContext, useCallback } from 'react';
import { useLocation } from "react-router-dom";
import { useTable, useFilters, useSortBy, useRowSelect } from 'react-table';
import { UserContext } from "../context/UserContext";
import { relatedCardsColumns } from '../helpers/columns'
import { Checkbox } from './Checkbox'
import BTable from 'react-bootstrap/Table';
export const NewTable = () => {
//const [ownedCardData, setownedCardData] = useState([]);
const userContext = useContext(UserContext);
const columns = useMemo(() => relatedCardsColumns, [])
let data = [];
if (userContext.dataLoaded) {. <--dataLoaded is set to true in context with userContext.data is populated from API response
console.log("context data loaded")
data = userContext.data
}
data = useMemo(() => data, [])
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state,
nextPage,
previousPage,
canNextPage,
canPreviousPage,
pageOptions,
setPageSize,
selectedFlatRows
} = useTable(
{
columns: columns,
data: ownedCardData
},
useFilters,
useSortBy,
useRowSelect,
hooks => {
hooks.visibleColumns.push(columns => [
// Let's make a column for selection
{
id: 'selection',
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<Checkbox {...getToggleAllRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<Checkbox {...row.getToggleRowSelectedProps()} />
</div>
),
},
...columns,
])
}
)
const { pageIndex, pageSize } = state;
return (
<div><p> The data is <b>{userContext.dataLoaded ? <> <p>loaded</p>
<BTable striped bordered hover size="sm" {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th {...column.getHeaderProps(column.getSortByToggleProps())}>
{column.render("Header")}
<span>
{column.isSorted ? (column.isSortedDesc ? ' ⬇️ ' : ' ⬆️') : ''}
</span>
{/* rendering column filter */}
<div>{column.canFilter ? column.render('Filter') : null}</div> </th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => {
return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>;
})}
</tr>
);
})}
</tbody>
</BTable>
<select value={pageSize} onChange={(e) => setPageSize(Number(e.target.value))}>
{[10, 25, 50, 100].map((pageSize) => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</select>
<pre>
<code>
{
JSON.stringify(data)
}
</code>
</pre> </>
:
'not'}</b> loaded.</p></div>
);
};