react19+nextjs+antd切换主题颜色

在 React 19 + Next.js + Ant Design 项目中实现主题切换功能,可以通过以下步骤完成。这里将提供完整方案,包含静态主题切换和动态实时切换两种方式。


一、基础配置(Ant Design 主题支持)

1. 安装必要依赖
npm install antd @ant-design/cssinjs
2. 配置 Next.js 支持 CSS-in-JS

修改 next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {experimental: {appDir: true,},transpilePackages: ['antd'],
};module.exports = nextConfig;
3. 创建主题配置文件

src/theme/themeConfig.ts

import type { ThemeConfig } from 'antd';// 基础主题配置
export const baseTheme: ThemeConfig = {token: {colorPrimary: '#1677ff',borderRadius: 6,},
};// 暗黑主题
export const darkTheme: ThemeConfig = {token: {...baseTheme.token,colorBgBase: '#141414',colorTextBase: '#f0f0f0',colorPrimary: '#177ddc',},algorithm: 'dark',
};// 自定义主题
export const customTheme: ThemeConfig = {token: {...baseTheme.token,colorPrimary: '#ff4d4f',},
};

二、静态主题切换方案(SSR 兼容)

1. 创建 ThemeProvider 组件

src/providers/ThemeProvider.tsx

'use client';import { ReactNode, useState } from 'react';
import { ConfigProvider, theme } from 'antd';
import { baseTheme, darkTheme, customTheme } from '@/theme/themeConfig';type ThemeType = 'light' | 'dark' | 'custom';export function ThemeProvider({ children }: { children: ReactNode }) {const [currentTheme, setCurrentTheme] = useState<ThemeType>('light');const getThemeConfig = () => {switch (currentTheme) {case 'dark':return darkTheme;case 'custom':return customTheme;default:return baseTheme;}};return (<ConfigProvider theme={getThemeConfig()}>{children}{/* 主题切换控件可以放在这里 */}</ConfigProvider>);
}
2. 在布局文件中使用

src/app/layout.tsx

import { ThemeProvider } from '@/providers/ThemeProvider';export default function RootLayout({children,
}: {children: React.ReactNode
}) {return (<html lang="en"><body><ThemeProvider>{children}</ThemeProvider></body></html>);
}

三、动态实时切换方案(含持久化)

1. 扩展 ThemeProvider
'use client';import { ReactNode, useEffect, useState } from 'react';
import { ConfigProvider, theme } from 'antd';
import { baseTheme, darkTheme, customTheme } from '@/theme/themeConfig';type ThemeType = 'light' | 'dark' | 'custom';export function ThemeProvider({ children }: { children: ReactNode }) {const [currentTheme, setCurrentTheme] = useState<ThemeType>('light');// 初始化时读取本地存储useEffect(() => {const savedTheme = localStorage.getItem('theme') as ThemeType || 'light';setCurrentTheme(savedTheme);}, []);// 主题变化时保存到本地存储useEffect(() => {localStorage.setItem('theme', currentTheme);document.documentElement.setAttribute('data-theme', currentTheme);}, [currentTheme]);const getThemeConfig = () => {switch (currentTheme) {case 'dark':return darkTheme;case 'custom':return customTheme;default:return baseTheme;}};const toggleTheme = () => {setCurrentTheme(prev => {if (prev === 'light') return 'dark';if (prev === 'dark') return 'custom';return 'light';});};return (<ConfigProvider theme={getThemeConfig()}>{children}<button onClick={toggleTheme}style={{ position: 'fixed', right: 20, bottom: 20 }}>切换主题</button></ConfigProvider>);
}
2. 添加全局 CSS 变量

src/app/globals.css

:root {--primary-color: #1677ff;
}[data-theme="dark"] {--primary-color: #177ddc;
}[data-theme="custom"] {--primary-color: #ff4d4f;
}

四、高级功能扩展

1. 主题色选择器
import { ColorPicker } from 'antd';function ThemeColorPicker() {const [color, setColor] = useState('#1677ff');return (<ConfigProvidertheme={{token: {colorPrimary: color,},}}><ColorPicker value={color} onChangeComplete={(color) => setColor(color.toHexString())}/></ConfigProvider>);
}
2. 使用 CSS 变量动态主题
// 在 ThemeProvider 中添加
useEffect(() => {document.documentElement.style.setProperty('--primary-color', getThemeConfig().token.colorPrimary);
}, [currentTheme]);

五、解决 Next.js 的 SSR 问题

1. 创建 useClientTheme Hook

src/hooks/useClientTheme.ts

'use client';import { useEffect, useState } from 'react';export function useClientTheme() {const [theme, setTheme] = useState<'light' | 'dark'>('light');useEffect(() => {// 只在客户端执行const savedTheme = localStorage.getItem('theme') || 'light';setTheme(savedTheme as 'light' | 'dark');}, []);return theme;
}
2. 修改组件使用方式
'use client';import { useClientTheme } from '@/hooks/useClientTheme';export default function ClientComponent() {const theme = useClientTheme();return (<div data-theme={theme}>{/* 内容 */}</div>);
}

六、完整实现流程图

UserUIThemeProviderLocalStorageConfigProvider点击切换主题按钮调用toggleTheme()保存新主题更新主题配置重新渲染应用样式显示新主题界面UserUIThemeProviderLocalStorageConfigProvider

七、最佳实践建议

  1. 性能优化

    • 使用 React.memo 避免不必要的重渲染
    • 将主题状态提升到最顶层组件
  2. TypeScript 强化

    type ThemeType = 'light' | 'dark' | 'custom';
    interface ThemeContextType {theme: ThemeType;setTheme: (theme: ThemeType) => void;
    }
    
  3. 服务端渲染兼容

    • 使用 dynamic 导入客户端组件
    • _document.tsx 中初始化主题
  4. 测试方案

    // 测试主题切换
    test('should toggle theme correctly', () => {render(<ThemeProvider />);const button = screen.getByText('切换主题');fireEvent.click(button);expect(localStorage.getItem('theme')).toBe('dark');
    });
    

通过以上方案,你可以实现一个完整、高效且可维护的主题切换系统,同时兼容 Next.js 的服务端渲染特性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915347.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915347.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Modbus Slave 使用教程:快速搭建模拟从站进行测试与开发

文章目录Modbus Slave 使用教程&#xff1a;快速搭建模拟从站进行测试与开发步骤详解&#xff1a;搭建 Modbus Slave1. 安装与启动2. 配置从站连接 (Connection Setup)连接3. 定义从站数据 (设置寄存器/线圈映射)4. 设置初始值与变化模式 (可选但重要)5. 连接 Master 进行测试高…

通俗易懂神经网络:从基础到实现

引言 神经网络是人工智能和深度学习的核心&#xff0c;它模仿人脑的工作方式&#xff0c;通过数据学习复杂的模式。本文将以通俗易懂的方式讲解神经网络的基础知识&#xff0c;包括单层神经网络、多层神经网络&#xff0c;最后用Python代码实现一个简单的神经网络模型。1. 神经…

【Linux】基本指令详解(三) 指令本质、三个查找指令、打包压缩、重要热键、linux体系结构、命令行解释器

文章目录date指令cal指令find指令(指令本质也是文件)which指令file指令whereis指令alias指令grep指令top指令打包和压缩指令zip/unzip指令关于rzsz(linux与windows互传 )tar指令linux机器之间互传bc指令uname指令(查看linux机器体系结构)几个重要的热键[Tab]按键[Ctrl]c按键[Ct…

MSTP 多生成树协议

MSTP 多生成树协议 STP/RSTP 的局限性 所有 vlan 共享一颗生成树无法实现不同 vlan 在多条 Trunk 链路上的分担 二层链路负载均衡STP/RSTP 的局限——次优二层路径**次优二层路径&#xff08;Suboptimal Layer 2 Path&#xff09; 是指&#xff1a; ** 数据帧在交换网络中传输时…

Shell脚本-tee工具

一、前言在 Linux/Unix 系统中&#xff0c;tee 是一个非常实用的命令行工具&#xff0c;它可以帮助我们 同时将命令的输出打印到终端&#xff0c;并写入文件。这种“双路输出”机制在脚本调试、日志记录、自动化任务中非常有用。无论是做日志分析、脚本调试&#xff0c;还是编写…

走进Linux的世界:Linux基本指令(三)

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…

跨域详解与解决方案:从理论到实践的全面指南

目录 1. 跨域是什么?为什么它让人头秃? 为什么跨域问题让人抓狂? 跨域的本质 2. 跨域的罪魁祸首:同源策略与CORS 同源策略的来龙去脉 CORS:跨域的“通行证” 3. JSONP:古老但依然有用的跨域“黑科技” JSONP的原理 JSONP的优缺点 4. 代理服务器:跨域的“中间人…

深入详解:决策树在辅助诊断系统与临床决策支持中的应用及实现细节

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#,Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用…

【详细笔记】两类曲线积分转换

文章目录参考教程一两类曲线积分的联系参数方程曲线的切线方向余弦参考教程2两类曲线积分之间的关系物理意义解释证明思路参考教程一 3分钟帮你搞定两类曲线积分之间的联系&#xff08;弧长和坐标&#xff09; 两类曲线积分的联系 设平面曲线LLL上的第二类曲线积分∫LPdxQdy…

【成品设计】基于STM32F429的云端电子相册

V1《基于STM32F429的云端电子相册》 V1硬件框图&#xff1a;V1功能说明&#xff1a; 支持 softAP 配网。支持 HTTPS 客户端的 GET\POST 请求支持文件系统用于图片的存储。支持 LVGL 自定义 GUI。日历功能。STM32F429文件系统LVGLRGB LCD屏幕。屏幕尺寸480*480. 首次开机交互&am…

网络安全隔离技术解析:从网闸到光闸的进化之路

目录 一、网络安全隔离技术体系 1.1 网络安全隔离技术发展历程 1.2 隔离技术分类矩阵 1.3 核心隔离原理对比 二、网闸技术深度解析 2.1 GAP架构剖析&#xff08;Guarded Access Point System 安全隔离与信息交换系统&#xff09; 2.2 技术演进路线 三、光闸技术突破创新…

初识 二叉树

目录树什么是二叉树二叉树的五种状态满二叉树完全二叉树二叉排序树平衡二叉树二叉树的遍历B3642 二叉树的遍历P1305 新二叉树二叉树的深度P4913 【深基16.例3】二叉树深度相关例题训练&#xff1a;二叉树问题树 这是树&#xff08;拍摄于郑州轻工业大学&#xff0c;第一次郑州轻…

(1)Windows环境下安装Oracle

概述&#xff1a;Oracle数据库是一种网络上的数据库, 它在网络上支持多用户, 支持服务器/客户机等部署(或配置)。服务器与客户机是软件概念&#xff1a;它们与计算机硬件不存在一一对应的关系. 即:同一台计算机既可以充当服务器又可以充当客户机,或者一台计算机只充当服务器或只…

工业数据集成中间件工具OPC Router详细介绍

一、产品概述 OPC Router 是 Software Toolbox 旗下的一款面向工业数据集成与自动化的数据中间件工具&#xff0c;专注于实现各类工业系统之间的数据交互和自动化流程编排。它通过模块化的插件机制&#xff0c;打通 PLC、ERP、MES、数据库、MQTT、REST API 等不同系统之间的数…

消息队列 2.RabbitMQ的基本概念与使用

RabbitMQ 是一款基于 AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;协议的开源消息中间件&#xff0c;主要用于实现分布式系统中的消息传递&#xff0c;支持异步通信、系统解耦、流量削峰等场景。在 Java 生态中&#xff0c;RabbitMQ 被广泛应用&#xff0c;…

【web安全】SQL注入与认证绕过

目录 一、SQL注入漏洞 1.1 基础注入原理 1.2 实用注入Payload分类 逻辑绕过型 注释截断型 联合查询型 常见的万能密码-CSDN博客 二、登录绕过实战技巧 2.1 基础绕过手法 2.2 高级绕过技巧 编码绕过 多重注释 参数污染 三、密码重置漏洞利用 3.1 常见漏洞模式 3…

Python适配器模式详解:让不兼容的接口协同工作

一、模式定义与核心思想 适配器模式&#xff08;Adapter Pattern&#xff09; 是一种结构型设计模式&#xff0c;它通过创建一个中间层&#xff08;适配器&#xff09;&#xff0c;将不兼容的接口转换为客户端期望的接口。就像现实中的电源适配器&#xff0c;让不同国家的插头…

微信小程序列表数据上拉加载,下拉刷新

1.上拉加载数据&#xff0c;数据 下一页数据 前面的数据&#xff08;[...this.data.list, ...data.records&#xff09;2.当用户上拉加载过快时&#xff0c;会不停的调用接口&#xff0c;需要节流阀isLoading3.上拉加载到最后一页的判断&#xff0c;isFinish// pages/list.js…

【树上倍增 LCA DFS 前缀和】P10391 [蓝桥杯 2024 省 A] 零食采购|普及+

本文涉及知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 CDFS 树上倍增 LCA P10391 [蓝桥杯 2024 省 A] 零食采购 题目描述 小蓝准备去星际旅行&#xff0c;出发前想在本星系采购一些零食&#xff0c;星系内有 nnn 颗星球&#x…

PDF发票批量打印工具哪个好?高效打印发票的实用工具推荐

开小超市这几年&#xff0c;每月要打几十张进货发票做账&#xff0c;以前打印时总犯愁&#xff1a;有的发票 PDF 太大&#xff0c;打出来字小得看不清&#xff1b;有的又太窄&#xff0c;白白浪费半张纸。试过手动调整&#xff0c;每张都要改缩放比例&#xff0c;累不说&#x…