[英]How to make theme state be persistent when visiting/reloading/or going back a page on the browser?
How can I get my light/dark theme to be persistently saved as a state when a user reloads, visits a new page, or presses back on a browser, etc... Right now it's very inconsistent.当用户重新加载、访问新页面或按回浏览器等时,如何将我的浅色/深色主题永久保存为 state 等......现在它非常不一致。
Here is the index.js where I set up my theme.这是我设置主题的 index.js。 I wrap it around my components.
我将它包裹在我的组件周围。
index.js
import { ThemeProvider, CssBaseline } from "@material-ui/core";
import { createMuiTheme } from "@material-ui/core";
const MyThemeContext = React.createContext({});
export function useMyThemeContext() {
return useContext(MyThemeContext);
}
function MyThemeProvider(props) {
const [isDarkMode, setIsDarkMode] = useState(false);
const theme = useMemo(
() =>
createMuiTheme({
palette: {
type: isDarkMode ? 'dark' : 'light',
},
}),
[isDarkMode]
);
return (
<ThemeProvider theme={theme}>
<MyThemeContext.Provider value={{ isDarkMode, setIsDarkMode }}>
{props.children}
</MyThemeContext.Provider>
</ThemeProvider>
);
}
const routing = (
<Router>
<React.StrictMode>
<MyThemeProvider>
<CssBaseline />
<Header />
<Switch>
<Route exact path="/" component={App} />
<Route path="/register" component={Register} />
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
<Route path="/dash/:slug" component={Bucket} />
<Route path="/create" component={CreateBucket}/>
</Switch>
<Footer />
</MyThemeProvider>
</React.StrictMode>
</Router>
);
ReactDOM.render(routing, document.getElementById('root'));
I use a switch that activates the state of the theme, it's located in my header.我使用一个开关来激活主题的 state,它位于我的 header 中。
header.js
import React from 'react';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import CssBaseline from '@material-ui/core/CssBaseline';
import { makeStyles } from '@material-ui/core/styles';
import { NavLink } from 'react-router-dom';
import Link from '@material-ui/core/Link';
import Button from '@material-ui/core/Button';
import Switch from '@material-ui/core/Switch';
import { useMyThemeContext } from '../index';
const useStyles = makeStyles((theme) => ({
appBar: {
borderBottom: `1px solid ${theme.palette.divider}`,
},
link: {
margin: theme.spacing(1, 1.5),
},
toolbarTitle: {
flexGrow: 1,
},
}));
function Header() {
const classes = useStyles();
const {isDarkMode, setIsDarkMode} = useMyThemeContext();
return (
<React.Fragment>
<CssBaseline />
<AppBar
position="static"
color="default"
elevation={0}
className={classes.appBar}
>
<Toolbar className={classes.toolbar}>
<Switch
checked={isDarkMode}
onChange={() => setIsDarkMode(!isDarkMode)}
/>
</Toolbar>
</AppBar>
</React.Fragment>
);
}
export default Header;
How can I fix the inconsistency with the state not being saved?如何解决与未保存 state 的不一致问题? Thank you for the help!
感谢您的帮助!
you would use localStorage
to persist state in memory, passing a key name.您将使用
localStorage
将 state 保存在 memory 中,并传递一个键名。 on app reload your initial state would come from that value stored in localStorage
, if it's not set then !!
在应用程序上重新加载您的初始 state 将来自存储在
localStorage
中的那个值,如果它没有设置那么!!
will ensure the value is false
rather than null
将确保该值为
false
而不是null
Also pass to Provider
a function that updates state and also set the new value to localStorage
.还将更新 state 的 function 传递给
Provider
并将新值设置为localStorage
。 this way you don't need remember to set the value at localStorage
every place you consume the setIsDarkMode
这样你就不需要记住在你使用
setIsDarkMode
的每个地方都设置localStorage
的值
// if it's not set in localStorage value is null, then !! will set as false
const initialState = !!JSON.parse(localStorage.getItem('theme'))
function MyThemeProvider(props) {
const [isDarkMode, setIsDarkMode] = useState(initialState);
// you pass another function where you persist the value to localStorage
// given your code you may just create a toggle function where you don't need to pass a value. but you can change it to receive an argument
const toggleDarkMode = () => {
setIsDarkMode(themeMode => {
localStorage.setItem('theme', !themeMode)
return !themeMode
})
}
const theme = useMemo(
() =>
createMuiTheme({
palette: {
type: isDarkMode ? 'dark' : 'light',
},
}),
[isDarkMode]
);
return (
<ThemeProvider theme={theme}>
<MyThemeContext.Provider value={{ isDarkMode, toggleDarkMode }}>
{props.children}
</MyThemeContext.Provider>
</ThemeProvider>
);
}
and at your Header
you extract toggleDarkMode
instead:在你的
Header
你提取toggleDarkMode
代替:
function Header() {
const classes = useStyles();
const {isDarkMode, toggleDarkMode} = useMyThemeContext();
return (
<React.Fragment>
<CssBaseline />
<AppBar
position="static"
color="default"
elevation={0}
className={classes.appBar}
>
<Toolbar className={classes.toolbar}>
<Switch
checked={isDarkMode}
onChange={toggleDarkMode}
/>
</Toolbar>
</AppBar>
</React.Fragment>
);
}
export default Header;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.