adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
13.1k stars 1.14k forks source link

Updating columns in S2 TableView throws an error #7345

Open jluyau opened 3 weeks ago

jluyau commented 3 weeks ago

Provide a general summary of the issue here

When updating the columns in an S2/RAC TableView (i.e. hiding/showing columns), TableView throws an error

πŸ€” Expected Behavior?

TableView should not throw an error when the columns are changed, and columns should be updated to reflect the latest value.

😯 Current Behavior

The following error is thrown:

runtime.js:4 TypeError: Cannot read properties of undefined (reading 'key')
    at $7713593715703b24$export$49571c903d73624c (useTableCell.mjs:18:1)
    at Table.mjs:820:1
    at Component (CollectionBuilder.mjs:150:1)
    at renderWithHooks (react-dom.development.js:15486:1)
    at mountIndeterminateComponent (react-dom.development.js:20103:1)
    at beginWork (react-dom.development.js:21626:1)
    at beginWork$1 (react-dom.development.js:27465:1)
    at performUnitOfWork (react-dom.development.js:26596:1)
    at workLoopSync (react-dom.development.js:26505:1)
    at renderRootSync (react-dom.development.js:26473:1)

πŸ’ Possible Solution

No response

πŸ”¦ Context

Updating the columns prop to hide/show columns

πŸ–₯️ Steps to Reproduce

use the following story and press the first action button:

export const ColumnTest = () => {
  const [cols, setCols] = useState(columns);
  return (
    <>
      <div className={style({display: 'flex', gap: 8})}>
        <ActionButton onPress={() => setCols(columns.slice(0, 2))}>Hide end columns</ActionButton>
        <ActionButton onPress={() => setCols(columns)}>Reset columns</ActionButton>
      </div>
      <TableView aria-label="Many items table">
        <TableHeader columns={cols}>
          {(column) => (
            <Column width={100} minWidth={100} isRowHeader={column.isRowHeader}>{column.name}</Column>
          )}
        </TableHeader>
        <TableBody items={items}>
          {item => (
            <Row id={item.id} columns={cols}>
              {(column) => {
                return <Cell>{item[column.id]}</Cell>;
              }}
            </Row>
          )}
        </TableBody>
      </TableView>
    </>
  );
};

Version

s2: 0.4.1, react-aria-components: 1.4.1

What browsers are you seeing the problem on?

Chrome

If other, please specify.

No response

What operating system are you using?

OSX Sonoma 14.1.1

🧒 Your Company/Team

Adobe/Quarry

πŸ•· Tracking Issue

No response

LFDanLu commented 3 weeks ago

The root cause is that RAC Table expects the user to provided a list of dependencies to the TableBody in order to invalidate its items cache, so a case like this where the user wants to hide columns requires the user to provide the columns to the TableBody's dependency array. The provided example above works in RAC if col is provided to TableBody via dependencies={[cols]}.

S2 table doesn't allow the dependencies prop to be provided, and even when modified locally doesn't seem to have any effect on busting the cache despite using RAC Table under the hood, so this will need some investigation