Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
201 views
in Technique[技术] by (71.8m points)

css - Theme with React and Redux

i am trying to make a theme system on a react project that uses redux with a reducer that manages themes according to the user's local storage. But here my problem is that I used css files to define my styles on all of my components. However, I have all my logic with 2 javascript objects for light or dark mode. So I can't use js in css files unless I use css variables but I don't know how.

Here is my structure :

enter image description here

In my app.js I imported useSelector and useDispatch from react redux to access the global state :

import React from 'react';
import './App.css';
import Footer from './components/Footer';
import Header from './components/Header';
import Presentation from './components/Presentation';
import Projects from './components/Projects';
import Skills from './components/Skills';
import Timeline from './components/Timeline';
import { switchTheme } from './redux/themeActions';
import { useSelector, useDispatch } from 'react-redux';
import { lightTheme, darkTheme } from './redux/Themes';

function App() {

  const theme = useSelector(state => state.themeReducer.theme);
  const dispatch = useDispatch();
  
  return (
    <div className="App">
      <Header />
      <input type='checkbox' checked={theme.mode === 'light' ? true : false} 
      onChange={
        () => {
          if(theme.mode === 'light') {
            dispatch(switchTheme(darkTheme))
          } else {
            dispatch(switchTheme(lightTheme))
          }
      }} />
      <div className="top">
        <div className="leftPart">
          <Presentation />
          <Skills />
        </div>
        <Timeline />
      </div>
      <Projects />
      <Footer />
    </div>
  );

}

export default App;
question from:https://stackoverflow.com/questions/65898941/theme-with-react-and-redux

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can make use of data attributes. I have done the same in one my project like so :-

[data-color-mode="light"] {
  --color-focus-ring: #7daee2;
  --color-link-hover: #0039bd;
  --color-primary-bg: #eef6ff;
  --color-primary-text: #212121;
  --color-primary-border: #98b2c9;
  --color-secondary-bg: #c3d7f0;
  --color-secondary-text: #1a1a1a;
}

[data-color-mode="dark"] {
  --color-focus-ring: #5355d4;
  --color-link-hover: #4183c4;
  --color-primary-bg: #080808;
  --color-primary-text: #f1f1f1;
  --color-primary-border: #525252;
  --color-secondary-bg: #191919;
  --color-secondary-text: #d8d5d5;
} 

You can add the attribute to your top-level element (assuming div) like so:-

<div className="appContainer" data-color-mode="light" ref={appRef}> ></div>

Now use that appRef to change the data-color-mode attribute as well update the localstorage in one function. Updating the data-color-mode allows you to toggle between css variable colors easily. In my code, I have done this the following way:-

  const toggleColorMode = () => {
    const nextMode = mode === "light" ? "dark" : "light";
    // container is appRef.current only
    container?.setAttribute("data-color-mode", nextMode);
    setMode(nextMode);
  };

I am not using redux for this. Simply React Context API is being used by me but it's doable in your scenario as well.

You can take more reference from the repo - https://github.com/lapstjup/animeccha/tree/main/src

Note - I think there are other routes where people go with CSS-IN-JS but I haven't explored them yet. This solution is one of the pure css ways.

Fun fact - Github has implemented their newest dark mode in a similar way and that's where I got the idea as well. You can inspect their page to see the same attribute name :D.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...