当当前主题存储在本地时,如何在浅色和深色主题之间切换?
How do you toggle between light and dark themes while current theme is being locally stored?
我对反应还很陌生,我正在使用 Material-UI 实现一些新功能。当当前主题本地存储在浏览器中时,我正在尝试在浅色和深色主题之间切换。我希望在页面刷新时在本地存储当前主题。默认情况下,我的应用加载浅色主题。在切换开关之前,我验证了浅色主题是否在本地存储中。当我切换到深色主题时,我的应用程序更改为对应的应用程序,本地存储中的值也按预期更改。但是当我尝试将开关切换回浅色主题时,主题没有改变,只是我的本地存储值。不知道为什么。
如果有人有办法调整此代码来解决此问题或提出新想法,我将不胜感激。
Demo in CodeSandbox
CustomThemeContext.js
import React, { useState, createContext } from 'react';
import { ThemeProvider } from '@material-ui/core/styles';
import getTheme from '../components/MyThemes';
import Paper from '@material-ui/core/Paper';
export const CustomThemeContext = createContext(
{
currentTheme: 'normalTheme',
setTheme: null,
},
);
const CustomThemeProvider = (props) => {
const { children } = props
const currentTheme = localStorage.getItem('appTheme') || 'normalTheme'
const [themeName, _setThemeName] = useState(currentTheme)
const theme = getTheme(themeName)
const setThemeName = (name) => {
localStorage.setItem('appTheme', name)
_setThemeName(name)
}
const contextValue = {
currentTheme: themeName,
setTheme: setThemeName,
}
const paperStyle = {
height: "100vh",
}
return (
<div>
<CustomThemeContext.Provider value={contextValue}>
<ThemeProvider theme={theme}>
<Paper style={paperStyle}>
{children}
</Paper>
</ThemeProvider>
</CustomThemeContext.Provider>
</div>
)
}
export default CustomThemeProvider;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import CustomThemeProvider from './contexts/CustomThemeProvider';
ReactDOM.render(
<React.StrictMode>
<CustomThemeProvider>
<App />
</CustomThemeProvider>
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
App.js
import React, { useContext } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { CustomThemeContext } from './contexts/CustomThemeProvider';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Tooltip from '@material-ui/core/Tooltip';
import Typography from '@material-ui/core/Typography';
import BurgerButton from './components/BurgerButton';
import StarButton from './components/StarButton';
import Switch from '@material-ui/core/Switch';
import Button from '@material-ui/core/Button';
import AddCircleIcon from '@material-ui/icons/AddCircle';
import FormControlLabel from '@material-ui/core/FormControlLabel';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
width: 'auto',
},
title: {
flexGrow: 1,
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
}
}));
export default function App() {
const classes = useStyles();
const { currentTheme, setTheme } = useContext(CustomThemeContext);
const isDark = Boolean(currentTheme === 'darkTheme')
const handleThemeChange = (event) => {
const { checked } = event.target
if (checked) {
setTheme('darkTheme')
} else {
setTheme('normalTheme')
}
}
/*
switch (checked) {
case 'darkTheme':
return setTheme('darkTheme');
case 'normalTheme':
return setTheme('normalTheme');
default:
return null;
}
*/
return (
<div className="App">
<div className={classes.root}>
<AppBar position="static" title="Memo App">
<Toolbar>
<BurgerButton />
<Typography variant="h6" className={classes.title}>
Memo App
</Typography>
<Tooltip title="Toggle light theme/dark theme">
<FormControlLabel
control={<Switch checked={isDark} onChange={handleThemeChange} />}
label="Theme"
/>
</Tooltip>
<StarButton />
</Toolbar>
</AppBar>
<Button>
<AddCircleIcon />
</Button>
</div>
</div>
);
}
MyThemes.js
import normalTheme from './themes/normalTheme';
import darkTheme from './themes/darkTheme';
const themes = {
normalTheme,
darkTheme,
}
export default function getTheme(theme) {
return themes[theme]
}
在你的 ThemeProvider
组件 theme
道具上,克隆你分配给它的主题对象,它应该可以工作
<ThemeProvider theme={{...theme}}>
<Paper style={paperStyle}>
{children}
</Paper>
</ThemeProvider>
我对反应还很陌生,我正在使用 Material-UI 实现一些新功能。当当前主题本地存储在浏览器中时,我正在尝试在浅色和深色主题之间切换。我希望在页面刷新时在本地存储当前主题。默认情况下,我的应用加载浅色主题。在切换开关之前,我验证了浅色主题是否在本地存储中。当我切换到深色主题时,我的应用程序更改为对应的应用程序,本地存储中的值也按预期更改。但是当我尝试将开关切换回浅色主题时,主题没有改变,只是我的本地存储值。不知道为什么。
如果有人有办法调整此代码来解决此问题或提出新想法,我将不胜感激。
Demo in CodeSandbox
CustomThemeContext.js
import React, { useState, createContext } from 'react';
import { ThemeProvider } from '@material-ui/core/styles';
import getTheme from '../components/MyThemes';
import Paper from '@material-ui/core/Paper';
export const CustomThemeContext = createContext(
{
currentTheme: 'normalTheme',
setTheme: null,
},
);
const CustomThemeProvider = (props) => {
const { children } = props
const currentTheme = localStorage.getItem('appTheme') || 'normalTheme'
const [themeName, _setThemeName] = useState(currentTheme)
const theme = getTheme(themeName)
const setThemeName = (name) => {
localStorage.setItem('appTheme', name)
_setThemeName(name)
}
const contextValue = {
currentTheme: themeName,
setTheme: setThemeName,
}
const paperStyle = {
height: "100vh",
}
return (
<div>
<CustomThemeContext.Provider value={contextValue}>
<ThemeProvider theme={theme}>
<Paper style={paperStyle}>
{children}
</Paper>
</ThemeProvider>
</CustomThemeContext.Provider>
</div>
)
}
export default CustomThemeProvider;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import CustomThemeProvider from './contexts/CustomThemeProvider';
ReactDOM.render(
<React.StrictMode>
<CustomThemeProvider>
<App />
</CustomThemeProvider>
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
App.js
import React, { useContext } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { CustomThemeContext } from './contexts/CustomThemeProvider';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Tooltip from '@material-ui/core/Tooltip';
import Typography from '@material-ui/core/Typography';
import BurgerButton from './components/BurgerButton';
import StarButton from './components/StarButton';
import Switch from '@material-ui/core/Switch';
import Button from '@material-ui/core/Button';
import AddCircleIcon from '@material-ui/icons/AddCircle';
import FormControlLabel from '@material-ui/core/FormControlLabel';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
width: 'auto',
},
title: {
flexGrow: 1,
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
}
}));
export default function App() {
const classes = useStyles();
const { currentTheme, setTheme } = useContext(CustomThemeContext);
const isDark = Boolean(currentTheme === 'darkTheme')
const handleThemeChange = (event) => {
const { checked } = event.target
if (checked) {
setTheme('darkTheme')
} else {
setTheme('normalTheme')
}
}
/*
switch (checked) {
case 'darkTheme':
return setTheme('darkTheme');
case 'normalTheme':
return setTheme('normalTheme');
default:
return null;
}
*/
return (
<div className="App">
<div className={classes.root}>
<AppBar position="static" title="Memo App">
<Toolbar>
<BurgerButton />
<Typography variant="h6" className={classes.title}>
Memo App
</Typography>
<Tooltip title="Toggle light theme/dark theme">
<FormControlLabel
control={<Switch checked={isDark} onChange={handleThemeChange} />}
label="Theme"
/>
</Tooltip>
<StarButton />
</Toolbar>
</AppBar>
<Button>
<AddCircleIcon />
</Button>
</div>
</div>
);
}
MyThemes.js
import normalTheme from './themes/normalTheme';
import darkTheme from './themes/darkTheme';
const themes = {
normalTheme,
darkTheme,
}
export default function getTheme(theme) {
return themes[theme]
}
在你的 ThemeProvider
组件 theme
道具上,克隆你分配给它的主题对象,它应该可以工作
<ThemeProvider theme={{...theme}}>
<Paper style={paperStyle}>
{children}
</Paper>
</ThemeProvider>