nextui-org / nextui

🚀 Beautiful, fast and modern React UI library.
https://nextui.org
MIT License
21.66k stars 1.43k forks source link

[BUG] - Table with multiple select leads to matching error #1729

Open peterhijma opened 1 year ago

peterhijma commented 1 year ago

NextUI Version

2.1.13

Describe the bug

Using Remix (SSR) I have a table with "multiple select" enabled. It gives me this error:

Warning: Prop `data-key` did not match. Server: "row-header-column-fqu8o02955" Client: "row-header-column-al3odv09eyg"

I'd like to use SSR and don't feel too happy with wrapping the table with a ClientOnly component or something similar.

Thanks in advance! Very nice UI library.

Your Example Website or App

No response

Steps to Reproduce the Bug or Issue

  1. Enable multiple select for the table
  2. Error in the console

Expected behavior

There is no mismatch between server/client.

Screenshots or Videos

No response

Operating System Version

macOS

Browser

Chrome

thegostisdead commented 11 months ago

I'm having the same error using nextjs and "use client" https://stackblitz.com/edit/github-mfb9ja

image

fsolarv22 commented 11 months ago

same error here, and single select seems not to be working.

yukimasaki commented 9 months ago

I have same error.

seb350 commented 9 months ago

This happens because there's a mismatch between the server-rendered content and the client-side rendered content, specifically the data-key.

Since NextUI needs "use client" anyway, both your custom Table compoenent and the NextThemesProvider component can be imported using next/dynamic and disable SSR completely.

This: import TableX from './components/Table'; import { ThemeProvider as NextThemesProvider } from "next-themes";

To this: const TableX = dynamic( () => import('./components/Table'), { ssr: false } ); const NextThemesProvider = dynamic( () => import('next-themes').then((mod) => mod.ThemeProvider), { ssr: false } );

Then use as imported normally.

alexander-densley commented 8 months ago

also having this issue

Lucasmm016 commented 8 months ago

I'm also having the same problem, it only happens when multiple selection is activated, for single selection this doesn't happen.

elanclarkson commented 7 months ago

I also have this issue

cheestudio commented 7 months ago

@seb350 Why are you continuously posting this as a solution? It's a pretty poor band-aid for a much longer standing issue with the library.

seb350 commented 7 months ago

What do you mean continuously? I've posted it once lol or are your counting skills just like your programming ones?

cheestudio commented 7 months ago

You posted it here, as well, and it wasn't helpful there, either.

https://github.com/nextui-org/nextui/issues/779

seb350 commented 7 months ago

If you understand it, it's helpful.

rsemihkoca commented 7 months ago

Up nextjs 14.1.0. I used same table from documentation with custom style. Multiple selection error still continues

Prop data-key did not match. Server: "row-header-column-ei75sadomwv" Client: "row-header-column-j5dbc4t8d7"

Cainier commented 4 months ago

This error like [Hydration failed]()

Solution 1: You can using useEffect to run on the client only

https://nextjs.org/docs/messages/react-hydration-error#solution-1-using-useeffect-to-run-on-the-client-only

E.g.

'use client'

// usrs.tsx
export function Users() {
  const [ready, setReady] = useState<boolean>(false)
  const [selectedKeys, setSelectedKeys] = useState<Set<number>>(new Set())

  return ready && (
    <Table
      aria-label="Users"
      selectionMode="multiple"
      selectedKeys={selectedKeys}
      onSelectionChange={keys => setSelectedKeys(keys as Set<number>)}
    >
      ...
    </Table>
  )
}

Solution 2: Disable SSR on the parent component

https://nextjs.org/docs/messages/react-hydration-error#solution-2-disabling-ssr-on-specific-components

E.g.

// page.ts
import dynamic from 'next/dynamic'

const NoSSR = dynamic(async () => (await import('./users')).Users, { ssr: false })

export default async function PageUserManagement() {
    return <>
        <NoSSR />
    </>
}

Solution 3 on the nextjs official website: Using suppressHydrationWarning has no effect on this problem.

GVALFER commented 2 months ago

I have the same problem. Ok, it can be fixable using dynamic import, or a, useEffect. BUT the problem is: I load the data using SWR with fallbackData coming with server side to immediatly load the initial data. for that reason i can not use dynamic import or useEffect to load the table, otherwise load data from server side makes no sense. Why nextUI is too confuse ? It seems like everything was done in the middle of total confusion.

A solution (whats is not a solution) is use the useEffect hook, and set the initial state as "single" and when loaded, then pass to "multiple" but it give a flash, what sucks.

VichetN commented 1 month ago

@GVALFER Nice one!

Set default prop

isMultipleSelect = true,

`const [selectionMode, setSelectionModle] = React.useState("single");

useEffect(() => { if (isMultipleSelect) { setSelectionModle("multiple"); } }, [isMultipleSelect]);`

And pass it to Table props

`<Table isHeaderSticky={false} selectionMode={selectionMode} selectedKeys={selectedKeys} onSelectionChange={setSelectedKeys}

...... `

Solved my problem!

MisterHims commented 1 month ago

This happens because there's a mismatch between the server-rendered content and the client-side rendered content, specifically the data-key.

Since NextUI needs "use client" anyway, both your custom Table compoenent and the NextThemesProvider component can be imported using next/dynamic and disable SSR completely.

This: import TableX from './components/Table'; import { ThemeProvider as NextThemesProvider } from "next-themes";

To this: const TableX = dynamic( () => import('./components/Table'), { ssr: false } ); const NextThemesProvider = dynamic( () => import('next-themes').then((mod) => mod.ThemeProvider), { ssr: false } );

Then use as imported normally.

This actually works but the page briefly goes white before switching back to dark mode on refresh (FOUC) :/

@GVALFER Nice one!

Set default prop

isMultipleSelect = true,

`const [selectionMode, setSelectionModle] = React.useState("single");

useEffect(() => { if (isMultipleSelect) { setSelectionModle("multiple"); } }, [isMultipleSelect]);`

And pass it to Table props

<Table isHeaderSticky={false} selectionMode={selectionMode} selectedKeys={selectedKeys} onSelectionChange={setSelectedKeys} > ...... </Table>

Solved my problem!

Great, it's works and I find this solution much maintainable than all the others. Thanks!!

cdwmhcc commented 1 week ago
import {
  Table,
  ...
  type SelectionMode,
} from '@nextui-org/react'

function useTableSelectionMode(isMultipleSelect: boolean = true) {
  const [selectionMode, setSelectionMode] = React.useState('single')
  React.useEffect(() => {
    if (isMultipleSelect) {
      setSelectionMode('multiple')
    } else {
      setSelectionMode('single')
    }
  }, [isMultipleSelect])
  return selectionMode
}

export default function Test() {
  const selectionMode = useTableSelectionMode()
 <Table
    selectionMode={selectionMode}
    ......
}