主题提供者问题

时间:2020-07-25 08:40:32

标签: javascript reactjs react-hooks context-api use-context

我正在尝试为一个小项目设置主题提供程序。每次用户单击按钮时,应用程序主题(颜色)都应该更改。假设我在一个单独的文件中有四个主题,如下所示:

const themesArray = [
    { primaryColor: '#483639', secondaryColor: '#F7F7F7' },
    { primaryColor: '#fb7051', secondaryColor: '#333' },
    { primaryColor: '#60b494', secondaryColor: '#F7F7F7' },
    { primaryColor: '#afb5c0', secondaryColor: '#333' }
];

export default themesArray;

每次用户单击按钮(嵌套在特定组件中)时,计数器都会递增到3,如下所示:

import React, { useState, useContext } from 'react';
import themesArray from '../../styles/themesArray';

const ThemeContext = React.createContext();
const ThemeUpdateContext = React.createContext();

const useTheme = () => useContext(ThemeContext);
const useThemeUpdate = () => useContext(ThemeUpdateContext);

const ThemeProvider = ({ children }) => {

    const [state, setState] = useState({
        count: 0,
        primaryColor: themesArray[0].primaryColor,
        secondaryColor: themesArray[0].secondaryColor
    });

    const toggleTheme = () => {
        setState(prevState => ({
            count: prevState.count >= 3 ? 0 : ++prevState.count,
            primaryColor: themesArray[prevState.count].primaryColor,
            secondaryColor: themesArray[prevState.count].secondaryColor
        }));
    }

    return (
        <ThemeContext.Provider value={[state.primaryColor, state.secondaryColor]}>
            <ThemeUpdateContext.Provider value={toggleTheme}>
                {children}
            </ThemeUpdateContext.Provider>
        </ThemeContext.Provider>
    );

}

export { ThemeProvider, useTheme, useThemeUpdate };

计数器似乎可以正常工作,但是问题是我永远不会回到第一个对象值(我永远不会回到第一个主题颜色)。我的意思是,当我console.log(state.count, state.primaryColor, state.secondaryColor)收到此信息时:

0 #483639 #F7F7F7 ThemeContext.js:24
1 #fb7051 #333 ThemeContext.js:24
2 #60b494 #F7F7F7 ThemeContext.js:24
3 #afb5c0 #333 ThemeContext.js:24
0 #afb5c0 #333 ThemeContext.js:24
1 #fb7051 #333 ThemeContext.js:24
2 #60b494 #F7F7F7 ThemeContext.js:24
3 #afb5c0 #333 ThemeContext.js:24
0 #afb5c0 #333 ThemeContext.js:24

您知道为什么每次计数器值回到0时第一个对象值都会被最后一个对象值覆盖吗?

1 个答案:

答案 0 :(得分:2)

您正在改变状态++prevState.count which is a problem

治疗状态就好像是不变的

此外,您可以改用模数:

const toggleTheme = () => {
    setState(prevState => {
      const nextCount = prevState.count + 1;
      return {
        count: nextCount % 3,
        primaryColor: themesArray[nextCount].primaryColor,
        secondaryColor: themesArray[nextCount].secondaryColor
      };
    });
  };

完整示例:


const themesArray = [
  { primaryColor: "#483639", secondaryColor: "#F7F7F7" },
  { primaryColor: "#fb7051", secondaryColor: "#333" },
  { primaryColor: "#60b494", secondaryColor: "#F7F7F7" },
  { primaryColor: "#afb5c0", secondaryColor: "#333" }
];

const ThemeContext = React.createContext();
const ThemeUpdateContext = React.createContext();

const useTheme = () => useContext(ThemeContext);
const useThemeUpdate = () => useContext(ThemeUpdateContext);

const ThemeProvider = ({ children }) => {
  const [state, setState] = useState({
    count: 0,
    primaryColor: themesArray[0].primaryColor,
    secondaryColor: themesArray[0].secondaryColor
  });

  const toggleTheme = () => {
    setState(prevState => {
      const nextCount = prevState.count + 1;
      return {
        count: nextCount % 3,
        primaryColor: themesArray[nextCount].primaryColor,
        secondaryColor: themesArray[nextCount].secondaryColor
      };
    });
  };

  return (
    <ThemeContext.Provider value={[state.primaryColor, state.secondaryColor]}>
      <ThemeUpdateContext.Provider value={toggleTheme}>
        {children}
      </ThemeUpdateContext.Provider>
    </ThemeContext.Provider>
  );
};

const Button = () => {
  const [primaryColor] = useTheme();
  const toggle = useThemeUpdate();
  return (
    <button
      onClick={toggle}
      style={{ width: 500, height: 500, backgroundColor: primaryColor }}
    >
      Button
    </button>
  );
};

const App = () => {
  return (
    <ThemeProvider>
      <Button />
    </ThemeProvider>
  );
};

Edit brave-sunset-0xu96