1

Currently, I am developing a notice page.

I am using recoil to manage the state of whether the user has checked the notice or not.

The recoil state is also stored on local storage so that it does not disappear upon refresh.

If the user checked the notice, the recoil isNoticeView state is true, and if the announcement was not checked, it is false.

Therefore,

{!isNoticeView && (
  <div className="ml-1 h-2 w-2 rounded-full bg-status-error"></div>
)}

should be added according to the isNoticeView status value.

If I refresh the notice page after checking the notice

Hydration failed because the initial UI does not match what was rendered on the server

This error is happening.

The entire code of the notice page is as follows.

import NavBar from '@components/common/NavBar';
import PageLayout from '@components/layout/PageLayout';
import Image from 'next/image';
import { useState } from 'react';
import { noticeState } from '@recoil/noticeAtom';
import { useRecoilState } from 'recoil';

const Notice = () => {
  const [isNoticeView, setIsNoticeView] = useRecoilState<boolean>(noticeState);
  const [isView, setIsView] = useState<boolean>(false);

  return (
    <PageLayout>
      <NavBar isLeft={true} centerTitle="notice" />
      <section className="my-[68px]">
        <div className="mb-1 bg-white py-2 px-4">
          <div className="flex justify-between text-body2">
            <div className="flex">
              <p>hi</p>
              {!isNoticeView && (
                <div className="ml-1 h-2 w-2 rounded-full bg-status-error"></div>
              )}
            </div>
            <Image
              src={isView ? '/svg/dropdown.svg' : '/svg/dropup.svg'}
              alt="open"
              width={20}
              height={20}
              onClick={() => {
                if (isView) {
                  setIsView(false);
                } else {
                  setIsNoticeView(true);
                  setIsView(true);
                }
              }}
            />
          </div>
          {isView && <p className="py-5 text-body1">asdasd</p>}
        </div>
      </section>
    </PageLayout>
  );
};

export default Notice;

please help me ..

skwFE
  • 211
  • 3
  • 9

1 Answers1

0

Had the same issue, the solution can be pretty much found here: nextjs react recoil persist values in local storage: initial page load in wrong state

To elaborate: Recoil sets a state in the localStorage, which doesn't exist during server side rendering (SSR), hence the hydration error.
To fix it, use an additional flag, to check if you're doing SSR and disable it with useEffect.

So:

const [ssrCompleted, setSsrCompleted] = useState(false);
useEffect(() => setSsrCompleted(true), []);

and instead of using isNoticeView, always use isNoticeView && ssrCompleted.

Jakob
  • 1,156
  • 3
  • 15
  • 26