Open Clovel opened 2 years ago
Hey @Clovel could you try again using react:17
?, React 18 is still not fully supported by react-aria which is the library used by NextUI under the hood for creating tables, could you create a codesanbox/repository with the issue?
Using React & React DOM 17 completely broke my application.
Most errors come from ReactNode types being incompatible with React.ReactNode types, etc. Most likely I have a bunch of incompatible dependencies now.
for example, I have MUI v5 in my project alongside NextUI. MUI v5.10 required a version of @types/react-transition-group
that requires React 18.
Type 'React.ReactNode' is not assignable to type 'import("C:/Users/<myUser>/repository/<project>/<project>-frontend/node_modules/@types/react-transition-group/node_modules/@types/react/index").ReactNode'.
Also, it seems that React 18 is listed as a peer dependency for the react-aria
project you linked :
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
},
I tried reproducing the error in a sandbox, but it's not the same error... Anyway : https://codesandbox.io/s/nextui-react-18-error-tes3wg
EDIT : I had a rogue component in my table, the issue came back. I removed it and now the error is reproducible in the CodeSandbox.
As mentioned in https://github.com/adobe/react-spectrum/issues/3502#issuecomment-1242241141, this error is due to using CountersListItem
as children of Table.Body
, when it's expecting Table.Row
as children.
As mentioned in adobe/react-spectrum#3502 (comment), this error is due to using
CountersListItem
as children ofTable.Body
, when it's expectingTable.Row
as children.
Even if the CountersListItem
has Table.Row
as it's main component ?
Even if the
CountersListItem
hasTable.Row
as it's main component ?
Correct. Refactoring around that should work
Hey @Clovel as @devongovett (react-aria lead maintainer) mentioned here, The Table.Body
component only supports Table.Row
elements as children
Any reason for this limitation? I don't see a reason why we couldn't just pass the TableRow a custom as
prop or something like that. Main reason for this is you cannot integrate NextUI tables with any other library that has container elements. For example: react-beautiful-dnd
basically works out of the box with every UI library I've tried before aside from NextUI
Also curious how the builder works, if it looks for a tr
element within the table body and then find the cells in that, what does allowing container elements do that's so bad? I think all that would need to happen in that case is changing how the builder selects the elements, instead of looking for direct child elements, select all the tr
elements only for example
This behavior is non sense.
We can not do something like this, which would make sense if you need to do some processing per row, or event if you just want to encapsulate the row logic...
const MyRow = ({item, ...tableRowProps} : {item: FooItemType}) => {
const status = useFetchItemStatus(item)
return (
<TableRow {...tableRowProps} key={`example-${item.id}`}>
<TableCell>{item.foo}</TableCell>
<TableCell>{status || "loading satus"}</TableCell>
</TableRow>
)
}
....
// Then in the parent component you would do
...
<Table aria-label="Example table">
<TableHeader>
<TableColumn>Col A</TableColumn>
<TableColumn>Col B</TableColumn>
</TableHeader>
<TableBody>
{data.map(item => (
<MyRow item={item} />
))}
</TableBody>
</Table>
So honestly I don't understand the logic of not allowing this, this issue should remain opened imo since no solution was provided.
It's not a limitation we wanted, just a technical trade off required by internal implementation details. React actually makes it extremely difficult to build components that are aware of their children like Table needs to be in order to implement things like keyboard navigation.
That said, in React Aria Components, our new component library built on top of React Aria hooks, we found a new way of implementing collection components that lifts this restriction. The goal is to extract this new implementation out once it is stable and offer it to React Aria hooks users such as Next UI as well. So hopefully in the near future Next UI will be able to lift the restriction as well.
In the meantime, we've recommended moving the logic to a component inside the item rather than a wrapper. You could refactor your example like the following:
<TableBody>
{data.map(item => (
<TableRow key={`example-${item.id}`}>
<TableCell>{item.foo}</TableCell>
<TableCell><ItemStatus item={item} /></TableCell>
</TableRow>
))}
</TableBody>
function ItemStatus({item}) {
const status = useFetchItemStatus(item)
return status || 'loading status';
}
How I can add TableBody to <ReactSortable list={(column?.tasks || []).map((task) => ({ ...task, chosen: true, }))} setList={(newTasks) => { setColumns((prevColumns) => prevColumns.map((prevColumn) => prevColumn.id === column.id ? { ...prevColumn, tasks: newTasks } : prevColumn ) ); }} group="tasks" animation={150} tag={TableBody}
Have the same issue when trying to use DnD to reorder tabs. I'm assuming this is the same reliance on React Aria Components causing the underlying issue. Look forward to the updates.
What makes this quite cumbersome is that say if I have AccordionItem
s that do not render due to some logic inside them, now all that logic needs to be pulled up into the parent component so the AccordionItem
s can be conditionally removed. It basically promotes leaky abstractions. 😞
I did try to just assign getCollectionNode
to my custom components. It does stop complaining but it doesn't actually render the custom component properly.
So is there currently no way to breakout NextUI Table components into separate components? If so that is pretty disappointing considering the benefits you can gain from splitting things into server and client components.
Same issue with the <Listbox>
component... Considering the entire point of React is to breakdown complex UI into smaller components, this is a bit of a weird and unexpected behaviour.
@lazharichir MenuItem also
Yeah tried using the table again and got this same error. Unfortunately, it makes this table component fairly useless. Especially if you need to manage state for individual rows. There are refactoring work arounds but most of them are anti-patterns for react. Love this library otherwise.
Ran into this same issue, had to workaround using the nuqs library to re-render the table on query parameters update. Hope we can get a proper way to implement logic/state per row soon!
also got this issue with: DropdownItem
@devongovett @jrgarciadev How do you suggest using something like <InfiniteScroll />
from react-infinite-scroller
with an array of AccordionItem
s?
@viinaji I have the same problem with DropdownItem, were you able to solve it?
@alvaroaxo My goal was to separate each item in the menu, However, I encountered that error when using the component. To address this, I turned to the collections feature https://react-spectrum.adobe.com/react-stately/collections.html and the following is how I implemented it:
<DropdownMenu aria-label="Card Menu" items={CardMenuSections()}>
{section => (
<DropdownSection {...section}>
{/* @ts-ignore:disable-next-line */}
{item => <DropdownItem {...item} />}
</DropdownSection>
)}
</DropdownMenu>
type DropDownSectionType = {
key: string;
title?: string;
showDivider?: boolean;
items: (DropdownItemProps | undefined)[];
};
const CardMenuSections = (): DropDownSectionType[] => {
return [
{
key: 'options',
title: 'Options',
showDivider: true,
items: [LaunchConfig(), Extensions(), Pin()],
},
{
key: 'update',
title: 'Update',
showDivider: true,
items: [Update(), CheckForUpdate(), AutoUpdate()],
},
{
key: 'about',
title: 'About',
items: [DocPage(), Info()],
},
{
key: 'danger-zone',
items: [Uninstall()],
},
];
};
export const Pin = (): DropdownItemProps => {
const {cardId} = useCardData();
const isPinned = useIsPinnedCard(cardId);
const onPress = () => window.api.storageMgr.pinnedCards(isPinned ? 'remove' : 'add', cardId);
return {
key: 'pin-unpin',
title: isPinned ? 'Unpin' : 'Pin',
startContent: GetIconByName('Pin', {
className: `${isPinned ? 'rotate-45' : 'rotate-0'} transition duration-500`,
}),
className: 'cursor-default',
onPress,
};
};
I am facing same problem. Still no fix?
Why is this discussion marked as closed?
Why is this discussion marked as closed?
Indeed... I just ran into this issue myself. Pretty disappointing...
Reading the history of the bug, it seems at some point the answer was "some smartie pants created some super smart scheme in some library and didn't think this thru so now this is a limitation, tough luck.. here is a workaround and go on with your lives"
Workaround is that instead of doing something like (in my case it happened with an Accordion component, but same thing applies to Tables etc)
<Accordion>
<MyPrettyComponent>
{ item => <AccordionItem ..} ... >...</AccordionItem> }
</MyPrettyComponent>
</Accordion>
You refactor this to:
<MyNowNotSoPrettyComponent>{
items =>
<Accordion>{
items.map(item =>
<AccordionItem ...} ..> .. </AccordionItem>)
}</Accordion>
</MyNowNotSoPrettyComponent>
Worked for me.. and if you can't refactor your component for whatever reason, you are f.. ried.
I've found this issue to persist in almost every NextUI components that utilizes list items like Dropdown, ListBox, Select, Tabs, etc. To make a consistent theme in my App, I need to export the base component and all of its child component like this(image). This way I can just change any props from here and it'll be applied globally to my project. But this issue has created scattered abstraction everywhere I've to use the child component directly from nextui package instead of my @components
. Really hoping for some help if someone finds any solution.
@devongovett
It's not a limitation we wanted, just a technical trade off required by internal implementation details. React actually makes it extremely difficult to build components that are aware of their children like Table needs to be in order to implement things like keyboard navigation.
That said, in React Aria Components, our new component library built on top of React Aria hooks, we found a new way of implementing collection components that lifts this restriction. The goal is to extract this new implementation out once it is stable and offer it to React Aria hooks users such as Next UI as well. So hopefully in the near future Next UI will be able to lift the restriction as well.
In the meantime, we've recommended moving the logic to a component inside the item rather than a wrapper. You could refactor your example like the following:
<TableBody> {data.map(item => ( <TableRow key={`example-${item.id}`}> <TableCell>{item.foo}</TableCell> <TableCell><ItemStatus item={item} /></TableCell> </TableRow> ))} </TableBody> function ItemStatus({item}) { const status = useFetchItemStatus(item) return status || 'loading status'; }
Are there any updates on this?
Honestly, this argument really rings hollow. Everyone in the react ecosystem knows how to handle this. You are partially there; you just need to use inversion of control.
Instead of making it impossible to use standard and good practice for building one's react components, you just document the requirements of any child component(i.e. it must be forwardref, it must take this set of props and spread them on the top level element, etc) and use render props.
I've run into this issue trying to use almost every piece of this library and it's really making me reconsider using it, which is too bad. It was a candidate for becoming our primary internal component library at work and in my own personal projects. Unfortunately, the way it works now means that any react developer in our company that tries to use this library in a very sensible and reasonable way will run into extremely opaque errors. I would basically need to onboard everyone onto this issue specifically.
Are there any updates on this?
Yes! In our last React Aria release, we introduced a new collection implementation that supports custom wrappers, available in the @react-aria/collections
package. Here's an example of using it with React Aria hooks: https://stackblitz.com/edit/react-aria-collections?file=src%2FApp.tsx,package.json&terminal=dev
Next UI will need to do some work to adopt this in their implementation. One wrinkle is that there is a small breaking API change: you'll need to pass an id
prop instead of/in addition to a key
since we can no longer access React's key in the new implementation (React does not expose it inside component props). This means Next UI will either need to release a major version, or provide a way to opt-into the new API. I'm happy to work with the team to help with that if needed. Otherwise, after the internal changes in Next UI are made, it should be pretty transparent to users.
@niraj-khatiwada were you able to find a solution?
@niraj-khatiwada were you able to find a solution?
Nope, no solution.
Ran into this while trying to use react-intersection-observer
to build a lazily loaded table by wrapping <TableRow>
s in <InView>
. Would be really useful to have the ability to wrap rows!
I would also love to see a solution to this issue and an ability to move TableRow/TableCell to its own component, so that the various fetch requests of each table item is encapsulated.
any updates?
Next UI will need to do some work to adopt this in their implementation. [...] This means Next UI will either need to release a major version, or provide a way to opt-into the new API.
Any updates?
Describe the bug
When using the
Table
components, I get an error in the console from inside NextUI's code :I tried using the
Table
component two different ways :First, by using the render function as indicated by the documentation :
Then by using the
Array.map
method :In both cases, no ESLint or TypeScript errors are displayed in my IDE nor in my terminal.
These test were also made with the
Table.Body
section of the table.I am using :
"@nextui-org/react": "^1.0.0-beta.10"
"react": "^18.2.0"
"react-scripts": "5.0.1"
"typescript": "4.4.2"
Your Example Website or App
No response
Steps to Reproduce the Bug or Issue
CountersList.tsx
:CountersListItem.tsx
:Expected behavior
Render the table correctly
Screenshots or Videos
Operating System Version
Windows 10
Browser
Chrome