react-spectrum: Passing nested row into table causes getCollectionNode error
🐛 Bug Report
I have a table where I want to render a number of <Skeleton />
components that would contain a Row with five Cells both imported from the react-stately
package. The Skeleton animation component is dispalyed while the table data waits to be retrieved from the API. Obviously I would like to keep this in a separate file from the actual table file.
🤔 Expected Behavior
The rows should render normally while data from the API loads.
😯 Current Behavior
This error is returned.
Call Stack
$f8429209754fda4b9142d514065f4$export$CollectionBuilder.getFullNode$
app.2b21bd4ce9b6247290f9.bundle.js:31712:853
l
app.2b21bd4ce9b6247290f9.bundle.js:33546:5798
Generator._invoke
app.2b21bd4ce9b6247290f9.bundle.js:33546:5582
Generator.next
app.2b21bd4ce9b6247290f9.bundle.js:33546:6224
Object.n
app.2b21bd4ce9b6247290f9.bundle.js:20551:4865
_callee13$
app.2b21bd4ce9b6247290f9.bundle.js:31717:269
l
app.2b21bd4ce9b6247290f9.bundle.js:33546:5798
Generator._invoke
app.2b21bd4ce9b6247290f9.bundle.js:33546:5582
Generator.next
app.2b21bd4ce9b6247290f9.bundle.js:33546:6224
Object.n
app.2b21bd4ce9b6247290f9.bundle.js:20551:4865
💁 Possible Solution
🔦 Context
If I render the Skeleton Row directly into the table component without passing it from the Skeleton file it works just fine. What I can tell is that the map function from the table component doesn’t detect the nested components and throws this error.
💻 Code Sample
Table component
<Table scrollRef={ref} >
<Table.Head>
<Table.Heading align="center" className="border-r border-gray-300">
Head 1
</Table.Heading>
<Table.Heading align="center" className="border-r border-gray-300">
Head 2
</Table.Heading>
<Table.Heading align="center" className="border-r border-gray-300">
Head 3
</Table.Heading>
<Table.Heading align="center" className="border-r border-gray-300">
Head 4
</Table.Heading>
<Table.Heading align="center">
Head 5
</Table.Heading>
</Table.Head>
<Table.Body>
networkStatus
&& (new Array(50)
.fill({})).map((item, index) => (
/* eslint-disable-next-line react/no-array-index-key */
<Skeleton key={index} />
))
</Table.Body>
</Table>
Skeleton component
import React from "react";
import {
PageSkeleton, Table,
} from "components";
function Skeleton() {
return (
<Table.Row>
{(new Array(5).fill({})).map((cell, i) => (
<Table.Cell key={i} className="border-r border-gray-300">
<PageSkeleton.Text />
</Table.Cell>
))}
</Table.Row>
);
}
Working verison
<Table scrollRef={ref} >
<Table.Head>
<Table.Heading align="center" className="border-r border-gray-300">
Head 1
</Table.Heading>
<Table.Heading align="center" className="border-r border-gray-300">
Head 2
</Table.Heading>
<Table.Heading align="center" className="border-r border-gray-300">
Head 3
</Table.Heading>
<Table.Heading align="center" className="border-r border-gray-300">
Head 4
</Table.Heading>
<Table.Heading align="center">
Head 5
</Table.Heading>
</Table.Head>
<Table.Body>
networkStatus
&& (new Array(50)
.fill({})).map((item, index) => (
/* eslint-disable-next-line react/no-array-index-key */
<Table.Row>
{(new Array(5).fill({})).map((cell, i) => (
<Table.Cell key={i} className="border-r border-gray-300">
<PageSkeleton.Text />
</Table.Cell>
))}
</Table.Row>
))
</Table.Body>
</Table>
About this issue
- Original URL
- State: open
- Created 2 years ago
- Comments: 22 (11 by maintainers)
As mentioned above, collections don’t currently support wrapping
Item
.However, we’ve been experimenting with a way to allow this, you can try it out in our React Aria Components. See https://react-spectrum.adobe.com/react-aria/Select.html#reusable-wrappers Eventually, we’ll have this in all the docs and components, but for now it’s just React Aria Components.
I ran into the same problem with
useSelect
,<Item />
and thegetCollectionNode
error when I was modifying this tailwind example.Instead of including
Item
in my customDropdownItem
component, I ended up getting it to work like this:Hmmm I’m not sure why that is causing a problem specifically. You could check if the function, getCollectionNode, defined on Item gets carried over with the assign. It should be, but maybe some other piece is wrong due to the assign.
It’s not that it’s a problematic approach, so much as a path we haven’t tested. It’s fine to use React Aria hooks, they don’t reference the new collection work yet is all. That work is in the React Aria Components, and it’s currently an alpha while we make sure it’s in a stable state with an API we like. Eventually, the hooks docs will reference the new work.
Thanks for the info @snowystinger.
In my case it’s not a wrapper, but simply a re-export of
Item
fromreact-stately
for convenience:This way users can just import the custom
Select
and useSelect.Item
instead of having to importItem
separately.Are you suggesting that this is a problematic approach? I’m only using React Aria hooks, haven’t converted to Components yet.
Just an update, but @devongovett is currently experimenting with changes to collections as part of https://github.com/adobe/react-spectrum/discussions/2368 that will allow for custom wrappers around things like
Item
.