【问题标题】:Dark theme / with hooks深色主题/带挂钩
【发布时间】:2020-02-15 19:37:51
【问题描述】:

您好,我有一个自定义挂钩来定义我的主题

代码:

export default function App() {
  const [theme, setTheme] = usePersistedState('light');
  const toggleTheme = () => {
    setTheme(theme.type === 'light' ? 'dark' : 'light');
  };
  return (
    <ThemeProvider theme={theme}>
      <GlobalStyle />
      <div className="App">
        <button onClick={toggleTheme}>a</button>
      </div>
    </ThemeProvider>
  );

这是我的钩子:

import { darkTheme, lightTheme } from '../themes/index';

function usePersistedState(key) {
  const [state, setState] = useState(() => {
    switch (key) {
      case 'dark':
        return darkTheme;
      case 'light':
        return lightTheme;
      default:
        return lightTheme;
    }
  });
  console.log(state);
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(state.type));
  }, [key, state]);

  return [state, setState];
}

export default usePersistedState;

基本上每次我的状态发生变化时,我都会将它保存到本地存储中,但由于某种原因,它只能在第一次使用

当我第二次尝试更改主题时,我没有进入我的开关

编辑:

当我第一次在 gif 中显示我得到一个对象时,因为我输入了我的开关,但是当我尝试更改主题时,我只得到一个文本,因为我没有输入我的开关

【问题讨论】:

    标签: reactjs material-ui react-hooks


    【解决方案1】:

    您提供给useState 的参数将应用于第一次渲染。
    在接下来的渲染中,将应用您提供给setState 函数的内容(您提供 'light''dark',因此状态值将是 '亮''暗'

    对于您希望 switch case 运行每个状态更改的用例,useReducer 是比 useState 更好的选择(在我看来)。

    import { useReducer } from 'react';
    import { darkTheme, lightTheme } from '../themes/index';
    
    
    function usePersistedState(key) {
      const [state, dispatch] = useReducer(reducer, null, getTheme(key)); // first argument is the reducer function. second argument is the initial state. third argument is an init function (for complex initialization)
    
      const reducer = (state, action) => { // this will run on every state change (on every dispatch call)
        return getTheme(action.type)();
      }
    
      const getTheme = (themeType) => () => {
        switch (themeType) {
          case 'dark':
            return darkTheme;
          case 'light':
            return lightTheme;
          default:
            return lightTheme;
        }
      }
    
      console.log(state);
      useEffect(() => {
        localStorage.setItem('themeType', JSON.stringify(state));
      }, [state]);
    
      return [state, dispatch];
    }
    
    export default usePersistedState;
    

    从你的组件中你可以像这样调用 dispatch:

    export default function App() {
      const [theme, setTheme] = usePersistedState('light');
      const toggleTheme = () => {
        setTheme(theme.type === 'light' ? {type: 'dark'} : {type: 'light'});
      };
      return (
        <ThemeProvider theme={theme}>
          <GlobalStyle />
          <div className="App">
            <button onClick={toggleTheme}>a</button>
          </div>
        </ThemeProvider>
      );
    

    【讨论】:

    • 我有点困惑 :( 基本上,如果存储键中没有值,我将需要返回主题灯并能够在主题为暗或 lgiht 时保存,您可以帮助我?
    • 我会尽力帮助你的。什么是 state.type?是主题对象吗?
    • 这是主题的名称:export const darkTheme = { type: 'dark', colors: { primary: '# 222', secondary: '# DF2935', background: '# 333' , 文本: '#fff', }, };
    • 这样我就必须将我的主题导入我的自定义钩子和我的应用程序中
    • @MykonSpt 对于您的用例,useReducer 比 useState 更好。检查我的更新答案
    【解决方案2】:

    我想你忘了用 { type: ... } 在工具上添加对象包装器

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-12
      • 2019-05-10
      • 2013-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-08
      相关资源
      最近更新 更多