NodeJS 使用MUI V5最新版本切换黑暗模式与React、Next JS和本地存储

wwtsj6pe  于 2023-01-04  发布在  Node.js
关注(0)|答案(3)|浏览(147)

目前,我正在开发一个使用NEXT JSMUI 5最新版本以及GraphQL构建的Web应用程序。

我对这一点深信不疑

我确实想在LocalStorage中保持不断变化的黑暗模式,同时使用“www.example.com“提供的MUI指南实现https://mui.com/customization/dark-mode/#toggling-color-mode。

有没有人可以指导我,如果我切换开关,然后黑暗或光明模式将设置在本地存储?我需要你所有的建议。

我正在使用上下文API

import { createContext, useMemo, useState } from 'react'
import { createTheme, ThemeProvider } from '@mui/material/styles'

// TODO: Export this one
export const ColorModeContext = createContext({ toggleColorMode: () => {} })

const ThemeContext = ({ children }) => {
    const [mode, setMode] = useState('dark')

    const colorMode = useMemo(
        () => ({
            toggleColorMode: () => {
                setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'))
            },
        }),
        []
    )

    const theme = useMemo(
        () =>
            createTheme({
                palette: {
                    mode,
                    primary: {
                        light: '#757ce8',
                        main: '#3f50b5',
                        dark: '#002884',
                        contrastText: '#fff',
                    },
                    secondary: {
                        light: '#ff7961',
                        main: '#f44336',
                        dark: '#ba000d',
                        contrastText: '#000',
                    },
                },
            }),
        [mode]
    )

    return (
        <ColorModeContext.Provider value={colorMode}>
            <ThemeProvider theme={theme}>{children}</ThemeProvider>
        </ColorModeContext.Provider>
    )
}

export default ThemeContext

我在AppBar中实现了如下内容

// * ___main_appbar_function___
export default function MyAppBar(props) {
    const theme = useTheme()
    const colorMode = useContext(ColorModeContext)

    return (
        <NoSsr>
            <CssBaseline />
            <HideOnScroll {...props}>
                <AppBar color='inherit'>
                    <Toolbar variant='dense' component='div'>
                        <Box sx={root}>
                            <MySideBar />
                            <Typography component='div' variant='h5' textAlign='center'>
                                PJK
                            </Typography>
                            <Box sx={right}>
                                {/* <AuthModal /> */}
                                <motion.div
                                    whileTap={{ rotate: 360 }}
                                    // whileHover={{ rotate: 360 }}
                                    transition={{ type: 'spring', stiffness: 50 }}
                                >
                                    <IconButton onClick={refreshPage}>
                                        <RotateRightIcon />
                                    </IconButton>
                                </motion.div>

                                <IconButton
                                    sx={{ ml: 1 }}
                                    onClick={colorMode.toggleColorMode}
                                    color='inherit'
                                >
                                    {theme.palette.mode === 'dark' ? (
                                        <Brightness7Icon />
                                    ) : (
                                        <Brightness4Icon />
                                    )}
                                </IconButton>
                            </Box>
                        </Box>
                    </Toolbar>
                </AppBar>
            </HideOnScroll>
            <Toolbar />
        </NoSsr>
    )
}
n8ghc7c1

n8ghc7c11#

试试这个

const MODE = "mode";

const [mode, setMode] = useState(() => {

    // for the sake of solving this issues
   // ("ReferenceError: localStorage is not defined")
    if (typeof window !== 'undefined') {
        localStorage.getItem(MODE) || 'dark'
    }
});

const colorMode = useMemo(
    () => ({
        toggleColorMode: () => {
            setMode(prevMode => {
                const nextMode = prevMode === "light" ? "dark" : "light";
                localStorage.setItem(MODE, nextMode);
                return nextMode;
            });
        }
    }),
    []
);
np8igboo

np8igboo2#

这似乎为我工作,它检测系统偏好,并有一个选项,以切换黑暗和光明模式,可能不是最好的方式,它似乎为我工作。
App.js

import React from 'react';
import {
  ThemeProvider,
  createTheme,
  responsiveFontSizes,
} from '@mui/material/styles';
import { deepmerge } from '@mui/utils';
import useMediaQuery from '@mui/material/useMediaQuery';
import { getDesignTokens, getThemedComponents } from 'theme/Theme';
import { ColorModeContext } from 'config/color-context';

export default function App() {
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
  const [mode, setMode] = React.useState();

  React.useEffect(() => {
    setMode(prefersDarkMode ? 'dark' : 'light');
  }, [prefersDarkMode]);

  const colorMode = React.useMemo(
    () => ({
      toggleColorMode: () => {
        setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
      },
    }),
    []
  );

  let theme = React.useMemo(
    () =>
      createTheme(deepmerge(getDesignTokens(mode), getThemedComponents(mode))),
    [mode]
  );

  theme = responsiveFontSizes(theme);

  return (
    <ColorModeContext.Provider value={colorMode}>
      <ThemeProvider theme={theme}>
       ...         
      </ThemeProvider>
    </ColorModeContext.Provider>
  );
}

theme/Theme.js

import { amber, deepOrange, grey, blue, common } from '@mui/material/colors';

const palette = {
  light: {
    primary: {
      main: '#34C0AC',
      light: '#B1DED3',
      dark: '#00765A',
    },
  },
};

export const getDesignTokens = (mode) => ({
  palette: {
    mode,
    ...(mode === 'light'
      ? {
          primary: {
            main: palette.light.primary.main,
            light: palette.light.primary.light,
            dark: palette.light.primary.dark,
          },

          divider: amber[200],
          text: {
            primary: grey[900],
            secondary: grey[800],
          },
        }
      : {
          primary: deepOrange,
          divider: deepOrange[700],
          background: {
            default: deepOrange[900],
            paper: deepOrange[900],
          },
          text: {
            primary: '#fff',
            secondary: grey[500],
          },
        }),
  },
  typography: {
    fontFamily: [
      'Oswald',
      'Roboto',
      '"Helvetica Neue"',
      'Arial',
      'sans-serif',
    ].join(','),
    body1: {
      fontFamily: 'Poppins, Arial, sans-serif',
    },
  },
});

export const getThemedComponents = (mode) => ({
  components: {
    ...(mode === 'light'
      ? {
          MuiAppBar: {
            styleOverrides: {
              colorPrimary: {
                backgroundColor: grey[800],
              },
            },
          },
          MuiLink: {
            variant: 'h3',
          },
          MuiButton: {
            styleOverrides: {
              root: {
                borderRadius: 0,
                color: common.white,
                fontFamily:
                  "Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
                fontSize: 20,
                borderWidth: 2,
                '&:hover': {
                  borderWidth: 2,
                },
              },
            },
            variants: [
              {
                props: { variant: 'contained' },
                style: {
                  fontFamily:
                    "Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
                },
              },
              {
                props: { variant: 'outlined' },
                style: {
                  color: palette.light.primary.main,
                },
              },
              {
                props: { variant: 'primary', color: 'primary' },
                style: {
                  border: '4px dashed blue',
                },
              },
            ],
          },
          MuiList: {
            styleOverrides: {
              root: {},
            },
          },
          MuiMenuItem: {
            styleOverrides: {
              root: {
                color: common.white,
                alignItems: 'stretch',
                fontFamily:
                  "Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
              },
            },
          },
          MuiAccordion: {
            styleOverrides: {
              root: {
                color: common.white,
                fontFamily:
                  "Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
              },
            },
          },
        }
      : {
          MuiAppBar: {
            styleOverrides: {
              colorPrimary: {
                backgroundColor: blue[800],
              },
            },
          },
        }),
  },
});

config/color-context.js

import React from 'react';

export const ColorModeContext = React.createContext({
  toggleColorMode: () => {
    // This is intentional
  },
});

ThemeToggler.js

import React from 'react';
import { IconButton, Box } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
import { ColorModeContext } from 'config/color-context';

export default function SubHeaderNavigation() {
  const theme = useTheme();
  const colorMode = React.useContext(ColorModeContext);

  return (
    <Box
      sx={{
        display: 'flex',
        width: '100%',
        alignItems: 'center',
        justifyContent: 'center',
        bgcolor: 'background.default',
        color: 'text.primary',
        borderRadius: 1,
        p: 3,
      }}
    >
      {theme.palette.mode} mode
      <IconButton
        sx={{ ml: 1 }}
        onClick={colorMode.toggleColorMode}
        color="inherit"
      >
        {theme.palette.mode === 'dark' ? (
          <Brightness7Icon />
        ) : (
          <Brightness4Icon />
        )}
      </IconButton>
    </Box>
  );
}
cbjzeqam

cbjzeqam3#

试试这个

const Home = () => {
 const [isDarkMode, setDarkMode] = React.useState(false);

 React.useEffect(() => {
    window.localStorage.getItem('theme') == 'true' ? setDarkMode(true) : setDarkMode(false)
  }, [])

  const toggleDarkMode = () => {
    setDarkMode(!isDarkMode);
    window.localStorage.setItem("theme", !isDarkMode);
    console.log(window.localStorage.getItem('theme'))
  };

  return (
    <div className={(isDarkMode ? 'dark' : '') + ' main'}>
      
    </div>
  )
}

相关问题