next.js 使用recoil时出现“由于初始UI与服务器上呈现的内容不匹配,水合失败”错误

xqnpmsa8  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(184)

目前,我正在开发一个通知页面。
我正在使用反冲来管理用户是否检查了通知的状态。
反冲状态也存储在本地存储器上,以便它不会在刷新时消失。
如果用户勾选了公告,则reilisNoticeView状态为true,而如果公告未被勾选,则为false。
因此,我们认为,

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

字符串
应根据isNoticeView状态值添加。
如果我在查看通知后刷新通知页面
第一个月
发生此错误。
通知页面的整个代码如下。

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;


请帮帮我..

gcmastyq

gcmastyq1#

遇到同样的问题,解决方案可以在这里找到:nextjs react recoil persist values in local storage: initial page load in wrong state
详细说明:Recoil在localStorage中设置一个状态,该状态在服务器端渲染(SSR)期间不存在,因此出现了水合错误。
要修复它,请使用一个额外的标志来检查您是否正在执行SSR,并使用useEffect禁用它。
于是:

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

字符串
而不是使用isNoticeView,总是使用isNoticeView && ssrCompleted

相关问题