css React,使用localStrorage实现暗光模式

olhwl3o2  于 2023-01-18  发布在  React
关注(0)|答案(1)|浏览(133)

我试图使用use-local-storage来实现React中的主题转换器。
应用程序组件:

import './App.css';
import React from 'react';
import { Navbar, SearchBar, Header, Main, Chart, Map } from './components';
import { Routes, Route, BrowserRouter } from 'react-router-dom';
import useLocalStorage from 'use-local-storage';

function App() {

  //  a function that toggles between darkmode and lightmode in css
  const defaultDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
  const [theme, setTheme] = useLocalStorage('theme', defaultDark ? 'dark' : 'light');
  const switchTheme = () => {
    const newTheme = theme === 'light' ? 'dark' : 'light';
    setTheme(newTheme);
  }
  console.log(theme)

  return (
    <BrowserRouter>
      <div className='App' data-theme={theme} >
        <Header />
        <SearchBar />
        <Navbar switchTheme={switchTheme} />
        <Routes>
          <Route path="/" element={<Main />} />
          <Route path="/map" element={<Map />} />
          <Route path="/chart" element={<Chart />} />
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

导航栏组件:

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faMapLocationDot, faChartLine, faHouseUser } from '@fortawesome/free-solid-svg-icons'
import React from 'react'
import { Link } from 'react-router-dom'

const Navbar = ({switchTheme}) => {
  return (
    <nav className='nav'>
      <button onClick={switchTheme}>Toggle</button>
      <Link to='/'>
        <FontAwesomeIcon icon={faHouseUser} size='4x' color='blue' />
        <br></br>
        Home
      </Link>
      <Link to='/map'>
        <FontAwesomeIcon icon={faMapLocationDot} size='4x' />
        <br></br>
        Map</Link>
      <Link to='/chart'>
        <FontAwesomeIcon icon={faChartLine} size='4x' color='red' />
        <br></br>
        Chart</Link>

    </nav>
  )
}

export default Navbar

CSS:

*, *::after, *::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}

/****************** VARIABLES ******************/

  :root {
    --background-color:coral;
  }
  
  [data-theme="light"] {
    --background-color:red;
  }
  
  [data-theme="dark"] {
    --background-color:yellow;
  }


body {
background-color:var(--background-color);
font-family: 'Roboto', sans-serif;
font-size: 16px;
color: #333;
line-height: 1.5;
margin: 2vmin;
}

.App {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

/**********************  SearchBar  **********************/

form {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
max-width: 500px;
margin: 0 auto;
}

form > svg {
margin-left: -20px;
}

input {
font-size:inherit;
border-radius: 1vmin;
border: .5px solid #ccc;
padding: .5rem;
}

input:focus {
border-color: #333;
}


nav {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 0.5rem;
background-color: yellow;
border-bottom: 1px solid #eaeaea;
width: 10vw;
height: 50vh;
border: 3px dotted purple;
align-self: flex-start;
}

a {
text-decoration: none;
}



/* a:active  {
/* do sth with selected Link 
} */

我在App.js中从console.log(theme)获取了正确的值,但我无法更改整个应用程序的背景色。有什么办法可以解决这个问题吗?

kkih6yb8

kkih6yb81#

当您在body上设置主题,并尝试稍后通过App组件更改它时,您遇到了级联问题。请在body本身或html上添加data-themebody在前面,而不是在后面。
App.jsreturn之前添加useEffect可以工作:

useEffect(() => {
  document.documentElement.setAttribute("data-theme", theme);
}, [theme]);

在下面找到完整的示例和CodeSandbox:

import './App.css';
import React, {useEffect} from 'react';
import { Navbar, SearchBar, Header, Main, Chart, Map } from './components';
import { Routes, Route, BrowserRouter } from 'react-router-dom';
import useLocalStorage from 'use-local-storage';

function App() {
  //  a function that toggles between darkmode and lightmode in css
  const defaultDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
  const [theme, setTheme] = useLocalStorage('theme', defaultDark ? 'dark' : 'light');
  const switchTheme = () => {
    const newTheme = theme === 'light' ? 'dark' : 'light';
    setTheme(newTheme);
  }
  useEffect(() => {
    document.documentElement.setAttribute("data-theme", theme);
  }, [theme]);
  return (
    <BrowserRouter>
      <div className='App'>
        <Header />
        <SearchBar />
        <Navbar switchTheme={switchTheme} />
        <Routes>
          <Route path="/" element={<Main />} />
          <Route path="/map" element={<Map />} />
          <Route path="/chart" element={<Chart />} />
        </Routes>
      </div>
    </BrowserRouter>
  );
}
export default App;

相关问题