css 更改网站主题后,使用切换组件以外的App.js react

nhn9ugyo  于 2022-12-30  发布在  React
关注(0)|答案(4)|浏览(125)

我是新来的。我试图通过使用一个名为NavBar.js的组件中的开关来更改网站的整个主题。我找到的所有YouTube视频、教程和网站基本上都在教我如何在App.js文件中编写主题更改脚本,但我想从这个名为NavBar.js的文件中更改整个主题,因为开关就在那里。
本质上,如果用户在导航栏组件中切换主题开关,它就会完全改变主题。到目前为止,我只能改变主体的背景,但我想更改其他组件的背景(以及修改他们的文本颜色等)。这段代码只改变了主体的背景。我可以只是有一些方向,我需要做什么来完成这一点?我可以切换CSS样式表吗?

export default function Nav(){

   const[theme, setTheme] = useState('dark');

   const toggleTheme = () => {
    setTheme((theme) => (theme === 'dark' ? 'light' : 'dark'));

    if(theme === 'dark')
    {
        document.body.style = 'background: red;';
    }
    else{
        document.body.style = 'background: white;';
    }

   }
   
    return(
        <div className="main-container">
            <div>
                <Link to="home"><img src={logo} alt="logo" className="nav-icon"/></Link>
            </div>
            <div className='theme-Switch-container'>
            <Switch onChange={toggleTheme}/>  
            <h4 style={{position: 'relative', display: 'inline'}}>Switch Theme</h4>
            </div>

            <div>
                <NavbarOption icon={searchGlass} alt="search icon" option="Explore"/>
                <NavbarOption icon={bell} alt="bell icon" option="Notifications"/>
                <NavbarOption icon={profile} alt="profile icon" option="Profile" link="profile"/>
                <NavbarOption icon={forums} alt="forum icon" option="Forums"/>
                <NavbarOption icon={market} alt="market icon" option="Cybermarket"/>
                <NavbarOption icon={livestream} alt="livestream icon" option="Livestream"/>
                <NavbarOption icon={analytics} alt="analytics icon" option="Analytics"/>
                <NavbarOption icon={gear} alt="gear icon" option="Settings"/>
                <NavbarOption icon={help} alt="help icon" option="Help"/>
                {/* <Link to="" className="PostBtn">Post</Link> */}
                <button className="PostBtn">Post</button>
                {/* <div className="PostBtn">
                    <h3>Post</h3>
                </div> */}
            </div>
        </div>
    );
}
jdzmm42g

jdzmm42g1#

解决这个问题的一个好方法是使用redux或API。我会选择useContext来保持它的简单。
在您的App.js中,您可以如下设置上下文:

const ThemeContext = createContext(null); // keep in mind that you can set anything to creatContext as default values.

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <NavBar/>
      // add more components here that can use the default colors
    </ThemeContext.Provider>
 )
}

然后在任何组件中,您都可以使用useContext,如下所示:

function Panel({ title, children }) {
  const theme = useContext(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}

您可以从这里阅读更多关于useContext API的信息useContext
希望能有所帮助!

xdyibdwo

xdyibdwo2#

添加一个css类到body来保存主题状态,如dark,在你的css文件中,使用body.dark选择器来监听主题的变化。

const toggleTheme = () => {
  setTheme((theme) => (theme === 'dark' ? 'light' : 'dark'));
  document.body.classList.toggle("dark");
}

在css中,尝试类似于:

body.dark {
  background-color: darkred;
}

body.dark .PostBtn {
  background-color: black;
  color: white;
}
2w3rbyxf

2w3rbyxf3#

有两条路可走。
1.使用useContext保存主题值并在App.js中调用
1.在App.js中设置状态并在NavBar.js中更改状态
第二种方法是:
app.js

const[theme, setTheme] = useState('dark');
...
<NavBar theme={theme} setTheme={setTheme} .../>
...

NavBar.js

function NavBar(props){

   const {theme,setTheme} = props

   const toggleTheme = () => {
    setTheme((theme) => (theme === 'dark' ? 'light' : 'dark'));

    if(theme === 'dark')
    {
        document.body.style = 'background: red;';
    }
    else{
        document.body.style = 'background: white;';
    }

   }
...
rkttyhzu

rkttyhzu4#

如果您不想使用上下文,那么您完全可以使用一个简单的useEffect来切换主题和根类,并使用CSS选择器来实现组件样式的变化。

    • 示例**

第一,一个组件具有:

  • theme的状态
  • 用于切换theme的按钮
  • 每次切换主题时重新运行的useEffect
  • 这个useEffect只是将document.body的css类设置为theme的值。
const defaultTheme = "light";

const NavBar = () => {
  const [theme, setTheme] = useState(defaultTheme);
  useEffect(() => {
    document.body.setAttribute("class", theme);
  }, [theme]);

  return (
    <nav>
      <h3>Navbar</h3>
      <Button
        className="my-custom-button"
        onClick={() =>
          setTheme((prev) => (prev === "light" ? "dark" : "light"))
        }
      >
        Toggle theme ({theme})
      </Button>
    </nav>
  );
};

上面使用的定制按钮组件定义如下

const Button = ({
  children,
  ...props
}: PropsWithChildren<React.ButtonHTMLAttributes<HTMLButtonElement>>) => {
  // ...
  return <button {...props}>{children}</button>;
};

使用CSS为我们的自定义<Button className="my-custom-button" ... />创建主题

// global button styles
.my-custom-button {
  border-radius: 5px;
  padding: 2px 5px;
}

// dark theme button styles
.dark * .my-custom-button {
  background-color: black;
  color: white;
}

// light theme button styles
.light * .my-custom-button {
  background-color: hotpink;
  color: black;
}

一个codesandbox,它实际演示了这一点

相关问题