0

I am a Java developer trying to learn React and I have this issue where I updated a table to use react-table and now, whenever I either add or delete an item from my api response, I need to refresh the whole page to see the changes take place, whereas before I had my useEffect showing these changes immediately.

Below I have my complete piece of code after deleting pretty much everything else trying to find the root cause for this issue. If I use the commented out tbody instead of the one that uses react-table, I can still see my updates working fine and as expected.

It may be worth mentioning also that if I try to use setData inside of the useEffect piece the react-table won't even get populated.

const {useTable} = require('react-table')

const MainTable = ({dataTableObj}) => {

const [reports, setReports] = useState(dataTableObj.reports)

const getInitialData = () => reports.map(report => ({
    name: report.title,
    runDate: report.runDate,
    createdDate: report.createdDate,
    category: report.category.title,
    actions: report.id,
}));

const [data, setData] = useState(getInitialData)

const {
    getTableProps,
    getTableBodyProps,
    rows,
    prepareRow,
} = useTable(
    {
        columns,
        data,
    }
);

useEffect(() => {

    setReports(dataTableObj.reports)
    // setData(dataTableObj.reports)

}, [dataTableObj.reports]);

const onConfirmDelete = (id) => {

    deleteReport(id).then(() => {

        const del = reports.filter(report => id !== report.id)
        setReports(del)

    })
}

return (
    <div>
        <table {...getTableProps()}>
            <tbody {...getTableBodyProps()}>
            {rows.map((row, i) => {
                prepareRow(row)
                return (
                    <tr {...row.getRowProps()}>
                        <td>{row.original.name}</td>
                        <td>
                            <IconButton onClick={() => onConfirmDelete(row.original.actions)}>
                                <Delete/>
                            </IconButton>
                        </td>
                    </tr>
                )
            })}
            </tbody>
            {/*<tbody>*/}
            {/*{reports.map((item) => {*/}
            {/*    return [*/}
            {/*        <tr key={item.id}>*/}
            {/*            <td>{item.title}</td>*/}
            {/*            <td>*/}
            {/*                <IconButton onClick={() => onConfirmDelete(item.id)}>*/}
            {/*                    <Delete/>*/}
            {/*                </IconButton>*/}
            {/*            </td>*/}
            {/*        </tr>*/}
            {/*    ];*/}
            {/*})}*/}
            {/*</tbody>*/}
        </table>
    </div>
    )
}

export default MainTable

I think I've run out of ideas at this point on what I could be missing and may need some help or guidance please.

Thank you very much.

Francislainy Campos
  • 3,462
  • 4
  • 33
  • 81
  • 3
    First take the “require” out of the component, it doesn’t need to be included on every render. See what that does. – Alan P. Nov 01 '20 at 06:26
  • Hi, thank you for your help. I've moved this part outside the component but I'm afraid I still get the same issue. – Francislainy Campos Nov 01 '20 at 09:14
  • I’m looking at this on my phone so it’s harder to read, but is ‘dataTableObjs’ a prop of MainTable? If it is, you don’t need that useEffect that calls ‘setReports’ - that is already done where you initialize ‘reports’ – Alan P. Nov 02 '20 at 02:59
  • No worries. Yes, this is there for the "non react-table", as without it I get the same issue needing to reload the page when a new item is added to see the changes. But on a deletion it works fine without this for that piece. For the react-table piece, removing it has made no difference I'm afraid. – Francislainy Campos Nov 02 '20 at 03:08
  • So you add an item from the parent component and pass all the items into MainTable via dataTableObj? Remove the useEffect, console.log(dataTableObj), and add an item via the parent and see if that new item appears in the console.log – Alan P. Nov 02 '20 at 03:14
  • Yes, here it's where it comes from: https://github.com/francislainy/gatling_tool/blob/dev_test_react_table/src/components/Home.js#L157 I'll try to see if I know how to do what you just asked. – Francislainy Campos Nov 02 '20 at 03:22
  • Yes, sorry, the asking was easier than I thought after rereading your comment. So I removed useEffect, reloaded the page and I had 8 items both visibly and and on the console. I added another one and I got to see 9 in the console but still 8 on the page. Got the 9th one to appear after reloading the page. – Francislainy Campos Nov 02 '20 at 03:31

1 Answers1

2

I made this codesandbox to test: https://codesandbox.io/s/confident-drake-e47wm?file=/src/MainTable.js

If you toggle line 9 and 10 in MainTable.js, you will toggle it working and not working. It seems when you put the data into local state (as you do because you are mapping it), it won't re-render. Not exactly sure why this is, I've never used react-table, maybe it's in the docs somewhere.

So I think you will either need to:

  1. do the mapping in the parent and pass the data into MainTable already mapped, or
  2. wrap MainTable in another component that does the mapping and again pass the data into MainTable already mapped
  3. Maybe it could be done with a custom hook, I didn't try that.
Alan P.
  • 2,898
  • 6
  • 28
  • 52
  • Thank you Alan. Your answer makes lots of sense and I very much appreciate the effort of putting this sample together so I'm upvoting it. For some reason though, that didn't work either and when I try to pass the data from my parent to the table it won't even get populated. I've sent a message to the maintainers of the library under their discord chat and will see if they know whether this could be an issue with it or what I could be missing. I'll come back to update this post once a solution is found. – Francislainy Campos Nov 03 '20 at 03:30
  • Share a codesandbox with your code and I’ll have a look – Alan P. Nov 03 '20 at 17:42
  • Thank you. Let me get back to this with a bit more time, perhaps over the weekend and I'll get back here. – Francislainy Campos Nov 04 '20 at 04:37
  • 1
    Hi Alan, I tried again today and was able to make it work with your suggestion. It failed the first time I tried because the accessor on the datasource was using name instead of title, which is what I get from my api but it's working okay now. Thanks very much for your time and help on this. Much appreciated. – Francislainy Campos Nov 06 '20 at 03:31