TanStack / table

🤖 Headless UI for building powerful tables & datagrids for TS/JS - React-Table, Vue-Table, Solid-Table, Svelte-Table
https://tanstack.com/table
MIT License
24.93k stars 3.07k forks source link

Can't perform a React state update on a component that hasn't mounted yet #5026

Open tacomanator opened 1 year ago

tacomanator commented 1 year ago

Describe the bug

Error received when navigating to a table using getGroupedRowModel() such as:

  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getGroupedRowModel: getGroupedRowModel(),
  });

As seen in this example, navigating to the basic table works fine where as navigating to the grouped table produces an error in the console. The only difference between the two is getGroupedRowModel().

I am using the code from the examples pretty much as is (stripped down for simplicity).

Your minimal, reproducible example

https://github.com/tacomanator/tanstack-table-unmounted

Steps to reproduce

  1. Clone example, install dependencies, and run
  2. While viewing the console, navigate to the grouped table
  3. Observe error

Expected behavior

No error output

How often does this bug happen?

Every time

Screenshots or Videos

https://github.com/TanStack/table/assets/63794/30edbbcf-8f7e-459f-b624-b7d82aac3f0a

Platform

macOS, Chrome 115.0.5790.170 arm64

react-table version

8.9.3

TypeScript version

5.1.6

Additional context

No response

Terms & Code of Conduct

andrelillvede commented 1 year ago

I am having the same problem in version 8.9.1 when I call table.getRowModel() to conditionally render rows in tbody and I can confirm that it probably has something to do with getGroupedRowModel.

If i remove getGroupedRowModel: getGroupedRowModel() from the hook the error disappears.

timredband commented 1 year ago

I'm seeing this exact same issue today.

timredband commented 1 year ago

I investigated this issue this morning and discovered that the error only occurs when in dev mode. Same with @tacomanator's example. When I run the example in dev mode I get the error, but if I do a npm run build and npm start then the error disappears.

bastibuck commented 1 year ago

I think this is due to the fact that these errors don't show up in production builds but still happen.

Happy to be proven wrong.

timredband commented 1 year ago

I think it has something to do with pagination. When you add getGroupedRowModel it ends up calling setPagination in the render and that ends up calling setState.

So if you set onPaginationChange in the useReactTable definition to onPaginationChange: () => undefined then the error also goes away.

vktrl commented 1 year ago

I think this is due to the fact that these errors don't show up in production builds but still happen.

It's possible that it's a dev-only error because of React's strict mode which will double renders and effects. For me it's happens only on the second round of the very first render.

It's likely that there's a internal hook that's using useState in an useEffect for memoization. setState is called after the render but the component will already be unmounted in dev mode.

ivp-dev commented 1 year ago

This occurs here and exclusively in the context when the getGroupedRowModel function is utilized. It can be resolved by simply verifying whether the component is mounted before call setState in onStateChange. It seems somewhat hacky but can be helpful.

VitAndrGuid commented 11 months ago

This also happens on getFacetedUniqueValues

ranonuevo commented 11 months ago

same issue in getFacetedUniqueValues

0xTux commented 8 months ago

same issue in getFacetedUniqueValues

also facing the same

nekochan0122 commented 8 months ago

same issue in getFacetedUniqueValues

Same here, is there any other solution?

rasvanjaya21 commented 8 months ago

I faced a similar issue. in my case, the affected functionality is due to function getSortedRowModel() from checking "isEmpty" of my data which this caused the error , my temporary solution is :

getSortedRowModel: !data.isEmpty ? getSortedRowModel() : null

GentikSolm commented 8 months ago

Using latest version of tanstack @ 8.11.6, getting this when calling table.getIsAllRowsSelected() in dev mode. I can confirm this still errors when strict mode is off.

{
        id: "select-col",
        enableResizing: false,
        enableSorting: false,
        header: ({ table }) => (
          <div className="flex h-full w-full items-center justify-center">
            <input
              type="checkbox"
              className="rounded-sm bg-neutral-500 text-orange-600 focus:ring-0 focus:ring-offset-0"
              id="checkbox"
              checked={table.getIsAllRowsSelected()}
              onChange={table.getToggleAllRowsSelectedHandler()}
            />
          </div>
        ),
      });
    }

Temporary fix is to move the header component key into the actual rendering of the table and use an early check on the number of selected elements.

                if (header.id === "select-col") {
                  return (
                    <div
                      key={header.id}
                      className="sticky left-0 top-0 z-20 border border-gray-600 bg-neutral-900 px-2.5 py-1.5"
                    >
                      <div className="flex h-full w-full items-center justify-center">
                        <input
                          type="checkbox"
                          className="rounded-sm bg-neutral-500 text-orange-600 focus:ring-0 focus:ring-offset-0"
                          id="checkbox"
                          checked={!!Object.keys(rowSelection) ? table.getIsAllRowsSelected() : false}
                          onChange={table.getToggleAllRowsSelectedHandler()}
                        />
                      </div>
                    </div>
                  );
                }
mcsdevv commented 2 months ago

I receive this when using getRowModel but not when using any of the other getRow functions. Figure it's something getRowModel does during render.

9a8ri3L commented 1 month ago

With me this error occurred in 8.20.1 as well, in table.getColumn(<COLUMN_ID>) in the Toolbar component, while passing column prop, and updating the DataTableFacetedFilter shadcn-ui component.

Which is absolutely expected behavior when passing mutable props.

Updating column prop via useState hook, solved the problem.

const [statusCol, setStatusCol] = useState(null);

useEffect(() => {
    if (table.getAllColumns().length) {
      setStatusCol(table.getColumn('status'));
    }
  }, [table.getAllColumns().length]);

// then

{statusCol && (
  <DataTableFacetedFilter
    column={statusCol}
    // ...
  />
)}
dohomi commented 1 month ago

I receive this error as well. For now I disable getGroupedRowModel and the error is gone.

jon-turnbull commented 3 weeks ago

I've been looking for a solution to this problem for a while. After reading further up about the pagination state causing the error I added manualPagination: true to the useReactTable hook props and it seems to fix it.

My use case has no need for client side pagination, so I guess it would be ok to set manualPagination to true?

nabilfatih commented 3 weeks ago

just add:

const [isMounted, setIsMounted] = React.useState(false)

  // Fix error on react table, when the table is not mounted
  React.useLayoutEffect(() => {
    setIsMounted(true)
  }, [])

// react table hook, and other codes...

// Fix error on react table, when the table is not mounted
  if (!isMounted) return null
tacomanator commented 3 weeks ago

@nabilfatih as a workaround sure, but important to let people know this workaround will hurt performance and change the loading profile of their app.

alexander-densley commented 1 day ago

i get this same error on this line: table.getRowModel().rows?.length