網站搜尋

javascript - 有沒有方法可以在 React.FC 中抑制 hydration 警告?


有沒有辦法在 React.FC 中抑制 hydration 警告?我收到一個警告 Did not expect server HTML to contain a <div> in <div>,是因為 pause: isServer() 的原因,但我需要它停止不斷向伺服器請求。我能以某種方式替換這個東西,或者像這樣在組件中使用 supressHydrationWarning 嗎?

export const NavBar: React.FC<NavBarProps> = ({}) => {  
  const [{ fetching: logoutFetching }, logout] = useLogoutMutation();
  const [{ data, fetching }] = useMeQuery({pause: isServer()}); 
  console.log(data);
  const router = useRouter();
  ...
};

是否伺服器:

export const isServer = () => typeof window === 'undefined';

導覽列在佈局中:

import { Wrapper, WrapperVariant } from "./Wrapper";

interface LayoutProps {
  variant?: WrapperVariant;
}

export const Layout: React.FC<LayoutProps> = ({ children, variant }) => {
  return (
    <>
      <NavBar />
      <Wrapper variant={variant}>{children}</Wrapper>
    </>
  );
};

然後索引頁被包裹在佈局中

const Index = () => {
  const [variables, setVariables] = useState({
    limit: 15,
    cursor: null as null | string,
  });
  
  const [{ data, error, fetching }] = usePostsQuery({
    variables,
  });
  
  if (!fetching && !data) {
    return <div>query failed: {error?.message}</div>;
  }
  return (
    <Layout>
        ...
    </Layout>
  )
}

export default withUrqlClient(createUrqlClient, { ssr: true })(Index);
...

...並開啟 SSR 後匯出。

我正在使用 Next.JS 搭配 Chakra-UI,所以我想它會在這裡渲染吧?

import NextDocument, { Html, Head, Main, NextScript } from "next/document";
import { ColorModeScript } from "@chakra-ui/react";

export default class Document extends NextDocument {
  render() {
    return (
      <Html>
        <Head />
        <body>
          {/* Make Color mode to persists when you refresh the page. */}
          <ColorModeScript />
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

答案#1

如果你正在使用 NextJS,最簡單的解決方案是使用 next/dynamic。

import dynamic from 'next/dynamic'
const NavBar = dynamic(() => import("/path/of/NavBar"), { ssr: false }) //<- set SSr to false

答案#2

pause 選項在伺服器和客戶端應該具有相同的值。

const mounted = useMounted();

const [{ data, fetching }] = useMeQuery({pause: mounted === false}); 

檢查組件是否已掛載:

export const useMounted = () => {
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);

    return () => {
      setMounted(false);
    };
  }, []);

  return mounted;
};