Me gustaría implementar el cambio entre el tema oscuro/claro dinámicamente con Ant design v4.
Es posible personalizar el tema con otras importaciones CSS/LESS como está escrito aquí: https://ant.design/docs/react/customize-theme#Use-dark-theme
Pero no estoy seguro de cómo cambiar entre esos temas dinámicamente desde el código. Tengo una variable en mi aplicación React ( darkMode ) que indica si el tema oscuro se usa actualmente. Tengo que proporcionar los archivos CSS correctos cuando se cambia esta variable. Pero no puedo importar CSS dinámicamente solo cuando se cumple alguna condición, porque no es así como funcionan las importaciones.
Traté de hacer algo complicado con require como en el siguiente código, pero es un enfoque muy, muy malo y todavía no funciona correctamente (porque CSS se inyecta pero probablemente no se retira):
const Layout = () => { ... useEffect(() => { if (darkMode === true) { require("./App.dark.css") } else { require("./App.css") } }, [darkMode]) return ( <Home /> ) }Debería ser posible cambiar de tema de alguna manera porque ya está implementado en los documentos de diseño de Ant ( https://ant.design/components/button/ ):
¿Tienes alguna idea de cómo hacerlo?
¡Gracias!
El requisito condicional no bloqueará el uso del módulo previamente requerido. Por lo tanto, siempre que su condición coincida con la requerida, estará disponible en su aplicación. Por lo tanto, se utilizarán los dos módulos requeridos. En lugar de solicitarlos, inserte la hoja de estilo y elimínela para alternar entre ellos:
const head = document.head const dark = document.createElement('link') const light = document.createElement('link') dark.rel = 'stylesheet' light.rel = 'stylesheet' dark.href = 'antd.dark.css' light.href = 'antd.light.css' useEffect(() => { const timer = setTimeout(() => { if (darkMode) { if (head.contains(light)) { head.removeChild(light) } head.appendChild(dark) } else { if (head.contains(dark)) { head.removeChild(dark) } head.appendChild(light) } }, 500) return () => clearTimeout(timer) }, [darkMode])Esto es lo que estoy usando por ahora:
PD-
haga una carpeta llamada "temas" - tendría 6 archivos -> dark-theme.css, dark-theme.jsx, light-theme.css, light-theme.jsx, use-theme.js, theme-provider.jsx . Cada uno de ellos se describe a continuación.
tema-oscuro.css
import "~antd/dist/antd.dark.css";tema-oscuro.jsx
import "./dark-theme.css"; const DarkTheme = () => <></>; export default DarkTheme;luz-tema.css
@import "~antd/dist/antd.css";luz-tema.jsx
import "./light-theme.css"; const LightTheme = () => <></>; export default LightTheme;use-theme.js Un gancho personalizado que pueden usar diferentes componentes -
import { useEffect, useState } from "react"; const DARK_MODE = "dark-mode"; const getDarkMode = () => JSON.parse(localStorage.getItem(DARK_MODE)) || false; export const useTheme = () => { const [darkMode, setDarkMode] = useState(getDarkMode); useEffect(() => { const initialValue = getDarkMode(); if (initialValue !== darkMode) { localStorage.setItem(DARK_MODE, darkMode); window.location.reload(); } }, [darkMode]); return [darkMode, setDarkMode]; };proveedor de temas.jsx
import { lazy, Suspense } from "react"; import { useTheme } from "./use-theme"; const DarkTheme = lazy(() => import("./dark-theme")); const LightTheme = lazy(() => import("./light-theme")); export const ThemeProvider = ({ children }) => { const [darkMode] = useTheme(); return ( <> <Suspense fallback={<span />}> {darkMode ? <DarkTheme /> : <LightTheme />} </Suspense> {children} </> ); };cambiar index.js a -
ReactDOM.render( <React.StrictMode> <ThemeProvider> <App /> </ThemeProvider> </React.StrictMode>, document.getElementById("root") );ahora, en mi barra de navegación, supongamos que tengo un interruptor para alternar el tema. Así es como se vería -
const [darkMode, setDarkMode] = useTheme(); <Switch checked={darkMode} onChange={setDarkMode} />debes crear 2 componentes
el primero :
import './App.dark.css' const DarkApp =() =>{ //the app container }y el segundo :
import './App.light.css' const LightApp =() =>{ //the app container } y cree HOC para manejar darkMode así:
const AppLayout = () =>{ const [isDark , setIsDark] = useState(false); return ( <> { isDark ? <DarkApp /> : <LightApp /> } </> ) }En el ejemplo de Ant, una sugerencia es importar su archivo CSS o LESS de "modo oscuro" a su hoja de estilo principal.
// inside App.css @import '~antd/dist/antd.dark.css';En lugar de intentar cambiar las hojas de estilo, los estilos "oscuros" se combinan con los estilos base en una hoja de estilo. Hay diferentes formas de lograr esto, pero el patrón común será:
dark-mode de algún tipo en su CSSAquí hay un ejemplo de trabajo:
https://codesandbox.io/s/compassionate-elbakyan-f7tun?file=/src/App.js
En este ejemplo, alternar el estado de darkMode agregará o eliminará un className dark-mode en el contenedor de nivel superior.
import React, { useState } from "react"; import "./styles.css"; export default function App() { const [darkMode, setDarkMode] = useState(false); return ( <div className={`App ${darkMode && "dark-mode"}`}> <label> <input type="checkbox" checked={darkMode} onChange={() => setDarkMode((darkMode) => !darkMode)} /> Dark Mode? </label> <h1>Hello CodeSandbox</h1> </div> ); } Si darkMode es verdadero y el nombre dark-mode está presente, se usarán esos estilos:
h1 { padding: 0.5rem; border: 3px dotted red; } .dark-mode { background: black; color: white; } .dark-mode h1 { border-color: aqua; }Usando menos compilador en tiempo de ejecución:
https://medium.com/@mzohaib.qc/ant-design-dynamic-runtime-theme-1f9a1a030ba0
Importar menos código en contenedor
https://github.com/less/less.js/issues/3232
.any-scope { @import url('~antd/dist/antd.dark.less'); }