admin管理员组

文章数量:1296911

I am transitioning from React Table 6 to 7, which es with a lot of new changes as React Table 7 is now a headless utility library, built with lots and lots of hooks. This is much different from React Table 6. I am not too familiar with hooks, and haven't used them previously (I had read up on them a few months back), but am now sort of forced to get into the weeds of them, as my application relies heavily on this library.

Using the examples guide here, I am setting up an initial table in my react app, attempting to connect the table to the live data for my app which is fetched with Axios. However, I am struggling right out of the gate with an initial important functionality - having the Table ponent show / update the data that I am passing to it, but only after that data changes.

To help make clearer, I have created the following ponent:

import React from 'react';
import { useTable } from 'react-table';

function MyReactTable7Table({ tableData }) {

    // 1. Create Columns
    const columns = React.useMemo(
        () => [
            {
                Header: 'Name',
                columns: [
                    {
                        Header: 'Col Available From Start',
                        accessor: 'conferenceId'
                    },
                    {
                        Header: 'Col Avail After Parent Re-Render',
                        accessor: 'teamMarket'
                    }
                ]
            }
        ],
        []
    );

    // 2. Create Data
    const data = React.useMemo(() => tableData, []);

    // 3. Call Use Table
    const {
        getTableProps,
        getTableBodyProps,
        headerGroups,
        rows,
        prepareRow
    } = useTable({ columns, data });

    // 4. Return the HTML Table
    return (<>
        <table {...getTableProps()}>
            <thead>
                {headerGroups.map(headerGroup => (
                    <tr {...headerGroup.getHeaderGroupProps()}>
                        {headerGroup.headers.map(column => (
                            // Add the sorting props to control sorting. For this example
                            // we can add them into the header props
                            <th {...column.getHeaderProps()}>
                                {column.render('Header')}
                            </th>
                        ))}
                    </tr>
                ))}
            </thead>
            <tbody {...getTableBodyProps()}>
                {rows.map(
                    (row) => {
                        prepareRow(row);
                        return (
                            <tr {...row.getRowProps()}>
                                {row.cells.map(cell => {
                                    return (
                                        <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                                    );
                                })}
                            </tr>
                        );
                    }
                )}
            </tbody>
        </table>
    </>);
}

export default MyReactTable7Table;

This is pretty much copied directly from the example page, except rather than using mock data, I am passing the data that is fetched from the parent ponent and passed as a prop. Here's the problem though: although the data from the parent ponent does update (initially, a skinny table with only 5 columns is fetched, and then a larger table with 20 columns is fetched that replaces the first table in the parent ponents state), the UI doesn't update on my web app. (I think because the table ponent's internal state is not updating?)

Im my example, conferenceId is 1 of the initial 5 columns fetched, however teamMarket is one of the 20 but not one of the 5 initial columns. Although the parent ponent fetches the new data and rerenders, the Table Component does not update to show the new data in the new column.

I am figuring out hooks and headless ponents on the fly with this, and would like to follow best practices with using this library, because from the docs + examples, it seems like a very good and powerful table ponent for React.

Edit

To update and clarify quickly, maybe it is a bad pattern for the parent ponent to fire off 2 separate async Axios fetches to update the same parent state variable. I'm not sure. As I mentioned, and just to clarify, the 1st fetch quickly grabs a skinny version of the data, while the 2nd fetch grabs the full table. Because the parent state updates with the new data array, the array being passed as the tableData prop to <MyReactTable7Table /> changes as well.

It's tough to hook up live, because the bug / issue itself is related to the live data not updating correctly...

I am transitioning from React Table 6 to 7, which es with a lot of new changes as React Table 7 is now a headless utility library, built with lots and lots of hooks. This is much different from React Table 6. I am not too familiar with hooks, and haven't used them previously (I had read up on them a few months back), but am now sort of forced to get into the weeds of them, as my application relies heavily on this library.

Using the examples guide here, I am setting up an initial table in my react app, attempting to connect the table to the live data for my app which is fetched with Axios. However, I am struggling right out of the gate with an initial important functionality - having the Table ponent show / update the data that I am passing to it, but only after that data changes.

To help make clearer, I have created the following ponent:

import React from 'react';
import { useTable } from 'react-table';

function MyReactTable7Table({ tableData }) {

    // 1. Create Columns
    const columns = React.useMemo(
        () => [
            {
                Header: 'Name',
                columns: [
                    {
                        Header: 'Col Available From Start',
                        accessor: 'conferenceId'
                    },
                    {
                        Header: 'Col Avail After Parent Re-Render',
                        accessor: 'teamMarket'
                    }
                ]
            }
        ],
        []
    );

    // 2. Create Data
    const data = React.useMemo(() => tableData, []);

    // 3. Call Use Table
    const {
        getTableProps,
        getTableBodyProps,
        headerGroups,
        rows,
        prepareRow
    } = useTable({ columns, data });

    // 4. Return the HTML Table
    return (<>
        <table {...getTableProps()}>
            <thead>
                {headerGroups.map(headerGroup => (
                    <tr {...headerGroup.getHeaderGroupProps()}>
                        {headerGroup.headers.map(column => (
                            // Add the sorting props to control sorting. For this example
                            // we can add them into the header props
                            <th {...column.getHeaderProps()}>
                                {column.render('Header')}
                            </th>
                        ))}
                    </tr>
                ))}
            </thead>
            <tbody {...getTableBodyProps()}>
                {rows.map(
                    (row) => {
                        prepareRow(row);
                        return (
                            <tr {...row.getRowProps()}>
                                {row.cells.map(cell => {
                                    return (
                                        <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                                    );
                                })}
                            </tr>
                        );
                    }
                )}
            </tbody>
        </table>
    </>);
}

export default MyReactTable7Table;

This is pretty much copied directly from the example page, except rather than using mock data, I am passing the data that is fetched from the parent ponent and passed as a prop. Here's the problem though: although the data from the parent ponent does update (initially, a skinny table with only 5 columns is fetched, and then a larger table with 20 columns is fetched that replaces the first table in the parent ponents state), the UI doesn't update on my web app. (I think because the table ponent's internal state is not updating?)

Im my example, conferenceId is 1 of the initial 5 columns fetched, however teamMarket is one of the 20 but not one of the 5 initial columns. Although the parent ponent fetches the new data and rerenders, the Table Component does not update to show the new data in the new column.

I am figuring out hooks and headless ponents on the fly with this, and would like to follow best practices with using this library, because from the docs + examples, it seems like a very good and powerful table ponent for React.

Edit

To update and clarify quickly, maybe it is a bad pattern for the parent ponent to fire off 2 separate async Axios fetches to update the same parent state variable. I'm not sure. As I mentioned, and just to clarify, the 1st fetch quickly grabs a skinny version of the data, while the 2nd fetch grabs the full table. Because the parent state updates with the new data array, the array being passed as the tableData prop to <MyReactTable7Table /> changes as well.

It's tough to hook up live, because the bug / issue itself is related to the live data not updating correctly...

Share Improve this question edited Apr 2, 2021 at 21:16 halfer 20.5k19 gold badges109 silver badges202 bronze badges asked Apr 17, 2020 at 4:12 CanoviceCanovice 10.5k31 gold badges129 silver badges280 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

You have provided an empty array dependency to your useMemo which means that the memoized value of tableData is created and assigned to data and is never changed. You will need to provide dependency indicating when the useMemo should recalculate/regenerate the value.

In your case, there is no need of 2nd useMemo.

So remove below code and just use tableData

const data = React.useMemo(() => tableData, []);

Like this:

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

Building on the conversation @gdh and @canovice are having, you can both have the table update on state change AND use useMemo.

In Step 2 above, just add the tableData to the empty array and all the rest of your code will work and you can continue to use useMemo.

    // 2. Create Data - note `tableData` in the useMemo array
    const data = React.useMemo(() => tableData, [tableData]);

In this example, we're saying:

React, please memoize tableData (because it could be very costly to render) and rerender it ONLY when tableData changes.

What's going on here is very similar to what @gdh explained: the useMemo hook needs to be told to watch for updates. The value placed into the array is the value useMemo watches to know when to re-render. You could also include multiple values in that watcher array (that's why it's an array), so it would update whenever any of values change.

Reference doc on useMemo: https://reactjs/docs/hooks-reference.html#usememo

本文标签: javascriptRerendering Table component when parent passes new or updated dataStack Overflow