next.js 封装antd message全局组件

1,045 阅读1分钟

在server端无法执行,只能在client端执行

1.封装loading组件

// D:\study\next-js-learning\src\utils\antdGlobal.tsx
'use client'
import { App } from "antd";
import type { MessageInstance } from "antd/es/message/interface";
import type { ModalStaticFunctions } from "antd/es/modal/confirm";
import type { NotificationInstance } from "antd/es/notification/interface";

let message: MessageInstance;
let notification: NotificationInstance;
let modal: Omit<ModalStaticFunctions, "warn">;

const AppWrapper = () => {
  const staticFunction = App.useApp();
  message = staticFunction.message;
  modal = staticFunction.modal;
  notification = staticFunction.notification;
  return null;
};
export default AppWrapper;
export { message, notification, modal };

2.放置组件

放到这里,参考 样式闪烁问题

// D:\study\next-js-learning\src\lib\AntdRegistry.tsx
"use client";
import React from "react";
import { createCache, extractStyle, StyleProvider } from "@ant-design/cssinjs";
import type Entity from "@ant-design/cssinjs/es/Cache";
import { useServerInsertedHTML } from "next/navigation";
import { ConfigProvider } from "antd";
import zhCN from "antd/lib/locale/zh_CN";
import theme from "@/theme/antdTheme";
import 'dayjs/locale/zh-cn';
dayjs.locale('zh-cn');
import { App } from "antd";
import AntdGlobal from "@/utils/antdGlobal";
import dayjs from "dayjs";
const StyledComponentsRegistry = ({ children }: React.PropsWithChildren) => {
  const cache = React.useMemo<Entity>(() => createCache(), []);
  const isServerInserted = React.useRef<boolean>(false);
  useServerInsertedHTML(() => {
    // 避免 css 重复插入
    if (isServerInserted.current) {
      return;
    }
    isServerInserted.current = true;
    return (
      <style
        id="antd"
        dangerouslySetInnerHTML={{ __html: extractStyle(cache, true) }}
      />
    );
  });
  return (
    <StyleProvider cache={cache}>
      <ConfigProvider locale={zhCN} theme={theme}>
        <App>
          <AntdGlobal></AntdGlobal>
          {children}
        </App>
      </ConfigProvider>
    </StyleProvider>
  );
};

export default StyledComponentsRegistry;

3.放置组件

再把上面的放到app/layout.tsx

// D:\study\next-js-learning\src\app\layout.tsx
import React from "react";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import StyledComponentsRegistry from "../lib/AntdRegistry";
import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
  title: process.env.NEXT_PUBLIC_APP_NAME || "Next.js Antd Admin",
  description: "萌萌人小说站",
};
const RootLayout = ({ children }: React.PropsWithChildren) => {
  return (
    <>
      <html lang="en">
        <body className={inter.className}>
          <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
        </body>
      </html>
    </>
  );
};

export default RootLayout;

4.使用组件

在页面中使用:

// D:\study\next-js-learning\src\app\page.tsx
"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { App, Button, DatePicker } from "antd";

function Home() {
  const { message } = App.useApp();
   /**
   * 路由跳转
   */
  const router = useRouter();
  const handleClick = (e: any) => {
    e.preventDefault();
    router.push("/home");
  };
  return (
    <main className="flex flex-col items-center justify-between p-24">
      <h1>我是首页</h1>
      <Button
        type="primary"
        onClick={() => {
          message.success("登录成功");
        }}
      >
        Primary Button
      </Button>
      <Link href={"/login"}>login</Link>
      <Link href={"/home"}>home页面</Link>
      <Link href={"/users"}>users页面</Link>
      <Link href={"/about"}>about页面</Link>
      <Button type={"link"} onClick={handleClick}>
        跳转到home页面
      </Button>

      <DatePicker />
    </main>
  );
}
export default Home;

5.在request.ts中使用message

import { message as AntdMessage } from "@/utils/antdGlobal";

····前略
AntdMessage.error(data.message);
····后略