glennflanagan / react-collapsible

React component to wrap content in Collapsible element with trigger to open and close.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SSR problems

bisubus opened this issue · comments

Describe the bug

Differences in generated HTML on server and client cause a warning in Next.js:

react-dom.development.js:67 Warning: Prop aria-controls did not match. Server: "collapsible-content-1632766367544" Client: "collapsible-content-1632766370864"

Currently it needs to be patched or excluded from server rendering to avoid the issue.

It's expected that this also causes problems with React server renderer in general.

To Reproduce

Use the component with Next.js

Expected behavior

The component could provide a way to override this behaviour for content id similarly to how it's done for trigger id with triggerElementProps.

Additional context

react-collapsible@2.8.4
next@11.1.0

A similar problem was also highlighted in an issue at React-accessible-accordion (springload/react-accessible-accordion#41)

In their scenario, they solved it with a feature request for resetIds(): springload/react-accessible-accordion#46 , similarly to the solution presented in React-tabs: https://github.com/reactjs/react-tabs#api

Don't know if that is plausible, but wanted to share the references in any case

commented

We're using Date.now() to represent a unique ID for aria controls, I think something like resetIDs would work

We have a frontity based application and when bumping our versions our production builds started to error out. After much troubleshooting I traced it back to this lib.

Pages that depended on this for their SSR were getting errors, but I think the dist version was swallowing them and just throwing out a vague Typescript: Cannot call a class as a function error.

Anyways, I pulled this lib did some hacking: Adding the ? fixed it for me. I think when the component is initialized prevState is null during the ssr process.
(prevState?.height === 'auto' || prevState?.height === 0) &&

I think if add the ability to override this.contentId this would be a quick workaround? The users using SSR can set it theirselves preventing the difference at re-hydration

Hey team, Appreciate your work for React-collapsible. Currently, I'm also facing the same issue. Any solution or a workaround for now?

@darshantejani007 the workaround for now would be to set your Collapsible to be a dynamic component so it doesn't go through SSR - not ideal but at least you can keep moving.

Thanks for the prompt reply. The plugin is working perfectly despite the error. It doesn't cause the application to break or something in my case. It's just a console error in the development mode. So I would prefer not to convert it into a dynamic component just yet.

Hello!
any news about the final fix for this issue?
And thanks for your work ! :)

React 18 added a useId hook for this purpose. I'm using a simple wrapper around Collapsible that looks like:

import { useId } from 'react'
import BaseCollapsible, { CollapsibleProps } from 'react-collapsible'

export function Collapsible(props: CollapsibleProps) {
  const id = useId()

  return (
    <BaseCollapsible
      {...props}
      contentElementId={`collapsible-content-${id}`}
      triggerElementProps={{
        ...props.triggerElementProps,
        id: `collapsible-trigger-${id}`,
      }}
    />
  )
}

image
My lighthouse audit failed because of this problem. I think it will be great to use react 18 hook useId instead of using plain Date.now() to represent a unique ID.