yjose/reactjs-popup

About SSR

moRanou opened this issue · 7 comments

Hello, I would like to ask a question about SSR,

Here are the errors I get in next.js
image

However, when I turned off the component SSR, it worked fine;How can I use this component without turning off the SSR functionality of the framework?
Looking forward to your reply. Thank you;

yjose commented

hey @moRanou ,
Try to wrap the popup component like the following, to make sure the component didn't render on the server-side

<div suppressHydrationWarning={true}>
       {process.browser && <Popup />}
 </div>

@yjose This has the downside of the trigger (ie a button) not prerendering. It would be great if there was native SSR support

Any update to this issue? it's still a problem for me.

Hello,

I am using next.js 12 and react 18. So I am using SSR. The following did cause me an error.

<Modal modalData={data}>
  <button type="button" aria-labe='modal'>
      View Details
    </button>
</HotelListModal>

const Modal = (children, data) => {

const [renderPopup, setRenderPopup] = useState(false)
 
return renderPopup ?  (
  <Popup trigger={children}>
     ....your content
  </Popup>
) : null
}

This is the one the solved it for me.

<Modal modalData={data} />

const Modal = (data) => {

const [open, setOpen] = useState(false);

return (
  <div>
   <button>View Details</button>
  <Popup open={open} closeOnDocumentClick modal onClose={() =>  setOpen(false)}>
    ....you content 
  </Popup
 </div>
)}

Rather than passing the button as a trigger declare it in the popup component within the same div. Controlled Popup -> https://react-popup.elazizi.com/controlled-popup/

The above workaround from @lukacspapp also works for me. Thank you ❤️.

A small issue in your example is that you also need to register onClick={() => setOpen(true)} on the button element.

I suppose this is the best way to fix this problem on Next.js.

import React, { useEffect, useRef, useState } from 'react';
import ReactPopup from 'reactjs-popup';

const ClientWrapperForReactPopup = (props) => {
  const [hasMounted, setHasMounted] = useState(false);

  useEffect(() => {
    setHasMounted(true);
  }, []);

  if (!hasMounted) {
    return props?.trigger ?? null;
  }

  return <ReactPopup {...props} />;
};

export default ClientWrapperForReactPopup;

This workaround sucks if you're testing your component. It's easy to run into a race condition.