Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 18 NextJS 12.1 - Hydration failed #1428

Open
davidkhierl opened this issue Mar 30, 2022 · 19 comments · Fixed by #1775
Open

React 18 NextJS 12.1 - Hydration failed #1428

davidkhierl opened this issue Mar 30, 2022 · 19 comments · Fixed by #1775

Comments

@davidkhierl
Copy link

Current Behavior

causing error: Hydration failed because the initial UI does not match what was rendered on the server.

Expected Behavior

should not cause error

Steps to Reproduce

  1. Fresh install nextjs app, will install react 18 by default
  2. include ReactPlayer component
@JulianLeviston
Copy link

JulianLeviston commented Apr 1, 2022

We got around this by effectively memoizing a boolean to track the loading state of it (and only rendering it once).

@sandrooco
Copy link

I‘d recommend to check on something like window (which is only available on client side). This needs to be done in useEffect for proper handling.
Then you simply conditionally display the player.

hasWindow && <ReactPlayer …/>

@Dovalization
Copy link

Like @sandrooco said, this can fix the issue.
Just a small component to show the full picture

video_player_component

@singh-inder
Copy link

singh-inder commented Apr 24, 2022

@davidkhierl
Dynamically import the react-player to remove this error.
This fixed the error for me.
No need to check for window object.

import dynamic from "next/dynamic";
const ReactPlayer = dynamic(() => import("react-player/lazy"), { ssr: false });

Make sure to implement this solution when using the above method
ref methods with dynamic imports

@cookpete
Copy link
Owner

cookpete commented May 2, 2022

These workarounds look good. It’s also possible this is fixed in [email protected] and [email protected]

@cookpete cookpete closed this as completed May 2, 2022
@degitgitagitya
Copy link

Um sorry, why this issue closed? I'm still getting hydration error with [email protected] , [email protected] , [email protected].

Dynamic import fixed the issue, but the onProgress props isn't working.

@singh-inder
Copy link

singh-inder commented May 13, 2022

@degitgitagitya It seems to be a issue with [email protected]. I downgraded to 2.10.0 and onProgress worked again.
I tested with [email protected] , [email protected] , [email protected]

#1453

@leo-cheron
Copy link

leo-cheron commented Jun 5, 2022

Rendering the component on the client side only isn't a solution and has negative performance impact, @cookpete this issue should be reopened.

@cookpete
Copy link
Owner

Rendering the component on the client side only isn't a solution

@mrgnou I’m happy to reopen this for visibility (although there is quite a backlog of issues now and I have little spare time) but what is the solution? What should be rendered on the server? This library loads third party scripts on the client to embed video players. What markup could we possibly render on the server that would make sense?

@cookpete cookpete reopened this Sep 19, 2022
@MuMaestro
Copy link

Is it an alternative is to include a empty iframe ? I suppose iframes are a good solution as they could be marked optionaly as unoptimized. Or maybe it could include a option for client-only, where it waits of an effect to set a boolean true if window is defined, it does defeat the pourpouse of optimization, but makes a transparent workaround for some providers.
(I'm saying thins whithout a look at source code)

@leo-cheron
Copy link

Rendering the component on the client side only isn't a solution

@mrgnou I’m happy to reopen this for visibility (although there is quite a backlog of issues now and I have little spare time) but what is the solution? What should be rendered on the server? This library loads third party scripts on the client to embed video players. What markup could we possibly render on the server that would make sense?

I'd say everything that can be rendered synchronously to avoid client side rerender.

  • Concerning native html player: pretty much everything.
  • Concerning embedded players: iframe with prefilled attributes if light mode isn't set to true.

I know maintaining such a lib is really time consuming, and thank you for your hard work so far, there ain't many lightweight react players out there!

migueloller added a commit to makeswift/makeswift that referenced this issue Jan 13, 2023
See cookpete/react-player#1428 for more
information about why ReactPlayer shouldn't be rendered on the server.
Ideally this is something that would be handled internally by the
ReactPlayer component, but alas, we must take care of it ourselves. We
should replace ReactPlayer with a more robust solution for our built-in
Video component.
migueloller added a commit to makeswift/makeswift that referenced this issue Jan 13, 2023
See cookpete/react-player#1428 for more
information about why ReactPlayer shouldn't be rendered on the server.
Ideally this is something that would be handled internally by the
ReactPlayer component, but alas, we must take care of it ourselves. We
should replace ReactPlayer with a more robust solution for our built-in
Video component.
migueloller added a commit to makeswift/makeswift that referenced this issue Jan 13, 2023
See cookpete/react-player#1428 for more
information about why ReactPlayer shouldn't be rendered on the server.
Ideally this is something that would be handled internally by the
ReactPlayer component, but alas, we must take care of it ourselves. We
should replace ReactPlayer with a more robust solution for our built-in
Video component.
@coreyward
Copy link

Seems like this should work in light mode at least, but it doesn't, suggesting that the issue is not just third-party scripts. In any case, those would normally be loaded after hydration, no? If nothing can be rendered server-side in some cases, I think that's fine, but it would be useful for the README to at least spell this out in the implementation directions rather than not.

@KelvinQiu802
Copy link

Solution in the Next.js doc

'use client'

import { useState, useEffect } from 'react'
 
export default function App() {
  const [isClient, setIsClient] = useState(false)
 
  useEffect(() => {
    setIsClient(true)
  }, [])
 
  return {isClient ? <ReactPlayer /> : <p>The video player cannot render on the server side</p>}
}

@qbounti
Copy link

qbounti commented Jan 31, 2024

Solution in the Next.js doc

'use client'

import { useState, useEffect } from 'react'
 
export default function App() {
  const [isClient, setIsClient] = useState(false)
 
  useEffect(() => {
    setIsClient(true)
  }, [])
 
  return {isClient ? <ReactPlayer /> : <p>The video player cannot render on the server side</p>}
}

This worked for me in next 14. Thanks!

@christopher-theagen
Copy link

Solution tweak that worked on this end: return null, not html:

'use client' // if using app dir

import { useState, useEffect } from 'react'
 
export default function App() {
  const [isClient, setIsClient] = useState(false)
 
  useEffect(() => {
    setIsClient(true)
  }, [])
 
  return {isClient ? <ReactPlayer /> : null}
}

@davidkhierl
Copy link
Author

davidkhierl commented Mar 4, 2024

Solution tweak that worked on this end: return null, not html:

'use client' // if using app dir



import { useState, useEffect } from 'react'

 

export default function App() {

  const [isClient, setIsClient] = useState(false)

 

  useEffect(() => {

    setIsClient(true)

  }, [])

 

  return {isClient ? <ReactPlayer /> : null}

}

Yes this fixes the hydration but ref won't work and other callback props like onProgress

@luwes
Copy link
Collaborator

luwes commented Apr 19, 2024

we have released a canary version that should resolve this issue in many cases.
Suspense is enabled and more importantly the current player's root element is rendered on the server.
please let me know if any issues arise.
https://www.npmjs.com/package/react-player/v/3.0.0-canary.0

@nitesh-lab
Copy link

Thanks Sir its Working Now.

@suuf
Copy link

suuf commented Nov 25, 2024

The hydration error remains when using the canary v3.0.0 and the React 19 Release Candidate 😢 Do we have to use ReactPlayer's fallback prop and set it to false? The fallback prop has a ReactElement type, not ReactElement | false?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.