table icon indicating copy to clipboard operation
table copied to clipboard

controlled / uncontrolled state the treatment of undefined

Open alissaVrk opened this issue 2 years ago • 6 comments

Describe the bug

I don't know if this is considered a bug, it is definitely an unexpected behavior

it seems that passing undefined to state.{expanded / columnSizing/ ...} or passing undefined to {onExpandedChange / onColumnSizingChange / ...} is treated as passing a value. and the state becomes controlled.

** There is another bug specific to the expanded state, it crashes if you pass undefined, though typescript allows it. but this is minor in my opinion

Your minimal, reproducible example

https://codesandbox.io/p/sandbox/friendly-wing-nwwp2w

Steps to reproduce

if you try to to hide columns nothing will happen.

but if you comment out

state: {
      columnVisibility: undefined,
    },
    onColumnVisibilityChange: undefined,

you can hide columns

if you comment out just onColumnVisibilityChange: undefined or just columnVisibility: undefined you still can't hide columns

Expected behavior

I think an undefined value should be treated as a "no value" and in my example, the column visibility state should be uncontrolled and I should be able to hide columns

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

-OS macOS -Browser chrome

react-table version

v8.7.9

TypeScript version

No response

Additional context

No response

Terms & Code of Conduct

  • [X] I agree to follow this project's Code of Conduct
  • [X] I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

alissaVrk avatar Mar 19 '23 09:03 alissaVrk

I can try and create a PR for this if you agree that this is wrong behavior

alissaVrk avatar Jun 15 '23 03:06 alissaVrk

This looks problematic to me too

jackson-3billion avatar Aug 23 '24 02:08 jackson-3billion

+1 This is still an issue and was very confusing to run into. At the very least, it would be helpful if this was included in the docs. I ran into the issue that expanded/onExpandedChange cannot be undefined for expansion to work. I want to create a TanStack Table wrapper component that can optionally take props related to expansion, but passing those directly to useReactTable causes issues if they are undefined.

function ReactTableWrapper<T>({ expanded, onExpandedChange}: Props<T>) {
    const table = useReactTable({
        // Other fields...
        state: {
            expanded, // Becomes controlled even if this is undefined
        },
        onExpandedChange, // Becomes controlled even if this is undefined
    });

    return (
        <Table table={table} />
    );
}

Instead, I need to do the following, which ensures that the expanded key is only provided when it isn't undefined.

state: {
    ...(expanded ? { expanded } : {}),
}

It looks like the problem is how the options are handled here: https://github.com/TanStack/table/blob/827b09814c659a5d196e63c7b827858db243a9cd/packages/react-table/src/index.tsx

BrendanC23 avatar Feb 05 '25 21:02 BrendanC23

+1 to the above.

This isn't technically a bug per se but I definitely think it's counterintuitive and not good practice to treat the absence of a value as different than the value being undefined.

I have a use case where I want to use the same table in two places within my app, one of which maintains table state and one that doesn't. I created a wrapper component that takes in optional table state but it breaks unexpectedly due to this behavior.

function MyTable({
  columnVisibility,
  onColumnVisibilityChange
}: {
  columnVisibility?: VisibilityState,
  onColumnVisibilityChange?: OnChangeFn<VisibilityState>
}) {
  const table = useReactTable({
    data: someData,
    columns: someColumns,
    getCoreRowModel: getCoreRowModel(),
    initialState: {
      columnOrder: defaultVisibility,
    },
    state: {
      columnVisibility, // breaks when this is undefined
    },
    onColumnVisibilityChange,
}

allan-cannon avatar Feb 19 '25 22:02 allan-cannon

This is very annoying, and is kind of a foot gun. It takes a minute to understand what's going on.

+1 Would love to see this fixed

adamghowiba avatar Feb 27 '25 01:02 adamghowiba

+1 It is especially annoying if you pass undefined expecting to be handled as "no value is passed", but it is handled as "undefined is passed as value" and TableState type says there should be state, but actual value for those case(at least i tried with columnOrder state) is undefined.

AndreiOrmanji avatar Nov 05 '25 14:11 AndreiOrmanji