skip to Main Content

I am trying to create a table that uses an api to access data from a database.

import { COLUMNS } from './ActivityColumns.js'
import { getTable } from "./ApiCall.js"

export const SortingTable = () => {

    const columns = useMemo(() => COLUMNS, [])
    const [aaa, setData] = useState([])

    const getData = () => {
        getTable('activity').then(result => {
            console.log('returning result')
            return result;
        })
    }

    const tableInstance = useTable({
        columns: COLUMNS,
        data: getData()
    },
    useSortBy)
}

The result in getData() is the expected one, an array of Object dicts [ {..}, {..}, ..., {..}]. The problem is that when tableInstance tries to set the data as the result of getData(), I get the following error: useTable.js:591 Uncaught TypeError: Cannot read properties of undefined (reading 'forEach')
The exact line that causes the error is from useTable.js:

  data.forEach((originalRow, rowIndex) =>
    accessRow(originalRow, rowIndex, 0, undefined, rows)
  )

Before using an API I used a json file that has the same structure as the API’s response: [{..}, {..}, {..}]. This one worked.

What goes wrong when trying to initiate with an API and how can I fix this error?

Edit 1: I tried to declare getData inside the hook

export const SortingTable = () => {

    const columns = useMemo(() => COLUMNS, [])
    
    const getData = () => {
        const [data, setData] = useState(null);
     
       const getData = () => {
         getTable('activity').then(result => {
           console.log('returning result')
           console.log(result)
           setData(result);
         })
       }
     
       getData();
     
       return data;
    }
    
    const tableInstance = useTable({
        columns: COLUMNS,
        data: getData
    },
    useSortBy)
    
    const { getTableProps, getTableBodyProps, headerGroups, footerGroups, rows, prepareRow } = tableInstance
}

2

Answers


  1. Your getData function does not have a return. This means calling getData() would give you undefined.

    Is useTable OK to work with an asynchronous function?
    If so, just return something from getData.

    If it expects its synchronous data you might need to put the results of getData into state so that it gets populated once available which in turn causes a rerender of your component and calling useTable again.

    import { COLUMNS } from './ActivityColumns.js'
    import { getTable } from "./ApiCall.js"
    
    export const SortingTable = () => {
    
        const columns = useMemo(() => COLUMNS, [])
        const [aaa, setData] = useState([])
        
        useEffect(() => {
                getData(); // <-----
        }, []);
        
        const getData = () => {
            getTable('activity').then(result => {
                setData(result); // <-----
            })
        }
        
        const tableInstance = useTable({
            columns: COLUMNS,
            data: aaa // <-----
        },
        useSortBy)
    }
    

    The reason why your JSON was loaded without issue and your fetching is problematic is probably because you just imported/required the JSON which is synchronous while getTable obviously returns a thenable/Promise.

    Login or Signup to reply.
  2. getData doesn’t return anything. So effectively you’re passing useTable an object {columns: COLUMNS, data: undefined}.

    One way to fix this is to declare getData inside your hook, and use state to save the result of the API call:

    const useTable = () => {
      const [data, setData] = useState(null);
    
      const getData = () => {
        getTable('activity').then(result => {
          console.log('returning result')
          setData(result);
        })
      }
    
      getData();
    
      // do whatever you want to do here with COLUMNS
    
      return data;
    }
    
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search