Javascript 在浏览器上访问/重新加载/返回页面时,如何使主题状态保持持久?
当用户重新加载、访问新页面或按回浏览器等时,如何使我的浅/暗主题持久保存为状态。。。现在情况很不稳定 这是我设置主题的index.js。我把它包在我的组件上 index.js 如何修复与未保存状态的不一致性?谢谢你的帮助 您将使用localStorage在内存中持久化状态,并传递一个键名。在应用程序重新加载时,您的初始状态将来自存储在localStorage中的值,如果未设置该值,则!!将确保该值为false而不是null 还向提供程序传递一个更新状态的函数,并将新值设置为localStorage。这样,您就不需要记住在使用setIsDarkMode的每个地方都设置localStorage的值 您将使用localStorage在内存中持久化状态,并传递一个键名。在应用程序重新加载时,您的初始状态将来自存储在localStorage中的值,如果未设置该值,则!!将确保该值为false而不是null 还向提供程序传递一个更新状态的函数,并将新值设置为localStorage。这样,您就不需要记住在使用setIsDarkMode的每个地方都设置localStorage的值Javascript 在浏览器上访问/重新加载/返回页面时,如何使主题状态保持持久?,javascript,reactjs,material-ui,Javascript,Reactjs,Material Ui,当用户重新加载、访问新页面或按回浏览器等时,如何使我的浅/暗主题持久保存为状态。。。现在情况很不稳定 这是我设置主题的index.js。我把它包在我的组件上 index.js 如何修复与未保存状态的不一致性?谢谢你的帮助 您将使用localStorage在内存中持久化状态,并传递一个键名。在应用程序重新加载时,您的初始状态将来自存储在localStorage中的值,如果未设置该值,则!!将确保该值为false而不是null 还向提供程序传递一个更新状态的函数,并将新值设置为localStorag
非常感谢你的帮助,这更有意义。感谢你对每件事如何运作的解释。如何使用此方法使header.js中的开关上的触发器工作?我得到一个类型错误:当我试图激活上述开关时,setIsDarkMode不是一个函数。我编辑了上面的帖子,以反映我是如何实现您的代码片段的。我认为最好保持您原来的帖子原样。您的版本可能会给未来的读者带来困惑,因为现在您正在实现问题的答案。关于错误,在我的示例中,我认为这是隐含的,一旦您将不同的函数名作为值传递给提供程序,您也会在标题处重命名,以便在从useMyThemeContextfwiw提取时使用toggleDarkMode。我编辑了答案,添加了更新的标题,以提供更多的清晰度。非常感谢您的帮助,这非常有意义。感谢你对每件事如何运作的解释。如何使用此方法使header.js中的开关上的触发器工作?我得到一个类型错误:当我试图激活上述开关时,setIsDarkMode不是一个函数。我编辑了上面的帖子,以反映我是如何实现您的代码片段的。我认为最好保持您原来的帖子原样。您的版本可能会给未来的读者带来困惑,因为现在您正在实现问题的答案。关于错误,我认为,在我的示例中,当您将不同的函数名作为值传递给提供程序时,您将在标题处重命名,以便在从useMyThemeContextfwiw提取时使用toggleDarkMode。我编辑了答案,添加了更新的标题,以提供更清晰的信息
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'));
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;
// 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>
);
}
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;