- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在我的 nextjs
应用程序中使用 mui5(Material Ui)
。我正在尝试实现 暗模式
。一切顺利。我想要一个功能,如果任何用户切换黑暗模式,那么它将被保存在本地存储中。然后当我刷新页面时,它会根据本地存储的值自动从本地存储和事件暗或亮模式获取值。如果用户第一次访问该站点,那么它应该会自动激活系统偏好模式。我的意思是如果本地存储中没有任何值,那么它应该自动激活系统偏好模式。我该怎么做。
这是我的代码-
_app.js
export default function MyApp(props) {
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
const [mode, setMode] = React.useState("light");
const colorMode = React.useMemo(
() => ({
// The dark mode switch would invoke this method
toggleColorMode: () => {
setMode((prevMode) =>
prevMode === 'light' ? 'dark' : 'light',
);
},
}),
[],
);
// Update the theme only if the mode changes
const muiTheme = React.useMemo(() => createTheme(theme(mode)), [mode]);
return (
<ColorModeContext.Provider value={colorMode}>
<CacheProvider value={emotionCache}>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={muiTheme}>
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</CacheProvider>
</ColorModeContext.Provider>
);
}
MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
emotionCache: PropTypes.object,
pageProps: PropTypes.object.isRequired,
};
工具按钮-
const theme = useTheme();
const colorMode = useContext(ColorModeContext);
<FormControlLabel
control={<MaterialUISwitch sx={{ m: 1 }} checked={theme.palette.mode === 'dark' ? false : true} />}
label=""
sx={{ mx: "0px" }}
onClick={colorMode.toggleColorMode}
/>
最佳答案
在这里,您可以看到我使用 Next.js 和 Material UI (5) 完成的示例:
我正在使用 Typescript,但如果您使用纯 JavaScript 也没关系
我们将有 2 个文件来独立修改特定属性。
darkTheme.ts
import { createTheme } from '@mui/material/styles'
const darkTheme = createTheme({
palette: {
mode: 'dark',
},
})
export default darkTheme
lightTheme.ts
import { createTheme } from '@mui/material/styles'
const lightTheme = createTheme({
palette: {
mode: 'light',
},
})
export default lightTheme
这里重要的是从上下文中检索的值和函数,按钮样式或图标可以是任何东西。
interface ThemeSwitcherButtonProps extends IconButtonProps { }
const ThemeSwitcherButton = ({ ...rest }: ThemeSwitcherButtonProps) => {
const { themeMode, toggleTheme } = useThemeContext()
return (
<Tooltip
title={themeMode === 'light' ? `Switch to dark mode` : `Switch to light mode`}
>
<IconButton
{...rest}
onClick={toggleTheme}
>
{themeMode === 'light' ? <DarkModeOutlined /> : <LightModeRounded />}
</IconButton>
</Tooltip>
)
}
export default ThemeSwitcherButton
我们使用 material ui 库中的 useMediaQuery
来检查浏览器的偏好模式。此 Hook 适用于客户端渲染和 ssr。
我们还使用 useLocalStorage
Hook 将状态保存在本地存储中,以便持久化。
我们用这个新的 Provider 包装了原来的 Material UI ThemeProvider(更名为 MuiThemeProvider),所以在 _app 文件中只需要一个 Provider
ThemeContext.tsx
import { createContext, ReactNode, useContext } from 'react'
import { ThemeProvider as MuiThemeProvider, useMediaQuery } from '@mui/material'
import lightTheme from '@/themes/light'
import darkTheme from '@/themes/dark'
import useLocalStorage from '@/react/hooks/useLocalStorage'
const DARK_SCHEME_QUERY = '(prefers-color-scheme: dark)'
type ThemeMode = 'light' | 'dark'
interface ThemeContextType {
themeMode: ThemeMode
toggleTheme: () => void
}
const ThemeContext = createContext<ThemeContextType>({} as ThemeContextType)
const useThemeContext = () => useContext(ThemeContext)
const ThemeProvider = ({ children }: { children: ReactNode }) => {
const isDarkOS = useMediaQuery(DARK_SCHEME_QUERY)
const [themeMode, setThemeMode] = useLocalStorage<ThemeMode>('themeMode', isDarkOS ? 'light' : 'dark')
const toggleTheme = () => {
switch (themeMode) {
case 'light':
setThemeMode('dark')
break
case 'dark':
setThemeMode('light')
break
default:
}
}
return (
<ThemeContext.Provider value={{ themeMode, toggleTheme }}>
<MuiThemeProvider theme={themeMode === 'light' ? lightTheme : darkTheme}>
{children}
</MuiThemeProvider>
</ThemeContext.Provider>
)
}
export {
useThemeContext,
ThemeProvider
}
_app.tsx
export default function MyApp(props: MyAppProps) {
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props
const getLayout = Component.getLayout ?? ((page) => page)
return (
<CacheProvider value={emotionCache}>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<ThemeProvider>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
{getLayout(<Component {...pageProps} />)}
</ThemeProvider>
</CacheProvider>
)
}
我从 here 获取源代码,并对其进行了一些修改,以便在 ssr 和客户端呈现不匹配的情况下可以与 Next.js 一起正常工作。
useLocalStorage 还使用另一个 useEventListener Hook ,以同步所有其他打开的选项卡中值的更改。
使用本地存储.tsx
// edited from source: https://usehooks-ts.com/react-hook/use-local-storage
// to support ssr in Next.js
import { Dispatch, SetStateAction, useEffect, useState } from 'react'
import useEventListener from '@/react/hooks/useEventListener'
type SetValue<T> = Dispatch<SetStateAction<T>>
function useLocalStorage<T>(key: string, initialValue: T): [T, SetValue<T>] {
// Read local storage the parse stored json or return initialValue
const readStorage = (): T => {
if (typeof window === 'undefined') {
return initialValue
}
try {
const item = window.localStorage.getItem(key)
return item ? (parseJSON(item) as T) : initialValue
} catch (error) {
console.warn(`Error reading localStorage key “${key}”:`, error)
return initialValue
}
}
// Persists the new value to localStorage.
const setStorage: SetValue<T> = value => {
if (typeof window == 'undefined') {
console.warn(
`Tried setting localStorage key “${key}” even though environment is not a client`,
)
}
try {
// Allow value to be a function so we have the same API as useState
const newValue = value instanceof Function ? value(state) : value
// Save to local storage
window.localStorage.setItem(key, JSON.stringify(newValue))
// We dispatch a custom event so every useLocalStorage hook are notified
window.dispatchEvent(new Event('local-storage'))
} catch (error) {
console.warn(`Error setting localStorage key “${key}”:`, error)
}
}
// State to store the value
const [state, setState] = useState<T>(initialValue)
// Once the component is mounted, read from localStorage and update state.
useEffect(() => {
setState(readStorage())
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
useEffect(() => {
setStorage(state)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [state])
const handleStorageChange = () => {
setState(readStorage())
}
// this only works for other documents, not the current one
useEventListener('storage', handleStorageChange)
// this is a custom event, triggered in writeValueToLocalStorage
// See: useLocalStorage()
useEventListener('local-storage', handleStorageChange)
return [state, setState]
}
export default useLocalStorage
// A wrapper for "JSON.parse()"" to support "undefined" value
function parseJSON<T>(value: string | null): T | undefined {
try {
return value === 'undefined' ? undefined : JSON.parse(value ?? '')
} catch (error) {
console.log('parsing error on', { value })
return undefined
}
}
useEventListener.tsx与网络中的完全相同。
这个例子的所有代码都可以在我的github repository中找到可以用作带有 Typescript、Nextjs 和 Material UI 的项目的起点。
您也可以尝试使用有效的 example here .
关于reactjs - Material ui 深色模式在页面刷新时重置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70657811/
我正在使用 Json 数据创建 ListView 。我正在填充一些图像、文本字段和一个按钮。当用户单击按钮时,按钮标题会发生变化。 问题是如果按钮被修改并且用户滚动 ListView 按钮重置为第一个
在我的 iOS 测验应用程序中,您有 15 秒的时间来回答问题。如果回答正确,则会出现第二个 View Controller ,然后单击第二个 View Controller 上的按钮将其关闭,并且第
我现在使用 Objective-C 在 iOS 中实现一个功能,即当 slider 值发生变化时,在 slider 的“节点”上方制作一个文本标签。文本标签文本是 slider 的当前值。 因此,我在
所以我有一个名为 AuthStack 的堆栈像这样 const AuthStack = ({ resetPassword, updateEmail }: any) => (
在我的 Flutter 小部件中,我有一个 StreamBuilder检查 snapshot.hasError在这种特定情况下,它将返回我的 ErrorRetryWidget() . builder:
如果我的手机 hibernate 或我离开应用程序发送短信/接听电话,我的应用程序将重新启动。我该如何防止这种情况? 我希望保存对象而不是基本数据类型。如果应用程序关闭或手机关闭,我不需要保存应用程序
我有一个如下所示的数据框: ID TIME AMT 1 0 50 1 1 0 1 2 0 1 3 0 1 4 0 1 4 5
我正在使用 org.eclipse.swt.widgets.Combo 类,我正在执行以下操作 Combo myCombo = new Combo(container, SWT.READ_ONLY);
我有一个 UISWitch 默认位置设置为 off 用户可选择将开关设置为on,我如何通过另一个按钮/操作将该开关重新关闭。 - (IBAction)switchToggled:(id)sender
我试图让玩家 Sprite 节点在接触到危险节点时重置。我怎样才能做到这一点?该代码不起作用。 if player.position == danger.position { player.p
我尝试在启动 UITests 时重置和恢复 UserDefaults 并在它们分别完成时恢复它们。这是在 AppDelegate 中使用的代码: func makeDefaultsBackup() {
我有一个公用事业账单分段表,其中每个分段表示一个月的千瓦时使用情况。我想将 12 人一组合计起来以获得年度账单。 变量bill_cd表示年度账单的最后一部分。 Data download cu
我刚刚使用 composer 为项目安装了一些依赖项。在这个项目中,我们使用 cartalyst/sentry-social 包。为此,我必须使用一个特殊的 GitHub 帐户——但我不知道我在使用该
我对 Marionette collectionView 有疑问。当我没有定义 el 时 var featureditems = new View.CarouselItems({ collection
我有一个knockout/mvc3应用程序。我正在将日期传递回 Controller 。 Controller public ActionResult PackageUpdate(Package up
我有 2 个 Activity ,在第二个 Activity 中,我阅读并对本地 JSON 文件进行了一些更改,它适用于我需要的所有内容,但是当我转到 mainActivity 然后返回到第二个 Ac
我有一个带有 .xib 的 UIViewController,它有 2 个名为“LblA”和“LblB”的 UILable。让我们将此 ViewController 称为“A”。 LblA 和 Lbl
该模型将 LSTM 作为其第一层。 在调用 model.predict 时说你传入了几个样本: >sam = np.array([ [[.5, .6, .3]], [[.6, .6, .3]], [[
我开始使用 Angular.JS。 我有许多共享同一个 Controller 的 View 。每个 View 都是收集存储在 Controller 中的数据的一个步骤: $routeProvider.
我已经使用 DDEV 几天了,它很棒。 但是我发现如果我运行 ddev ssh通过 ssh 进入容器,并通过 npm / aptitude 安装包等等,或者如果我在 ~/ 中创建新文件主目录,有时这些
我是一名优秀的程序员,十分优秀!