当我更新 context.provider 的值时,子组件不会改变颜色

When I update my context.provider's value, the child components don't change color

我在我的网站中实施多个颜色主题时遇到了一些问题。我做了一个连接到状态切换的按钮,每次状态切换时,useEffect 处理程序都会将我的 context.provider 的值设置为 dark/light 主题。当我记录 useEffect 处理程序时,它更改了主题,但是子组件不受它的影响。

这是我的 App.tsx:

import {
  useContext,
  useState,
  Provider,
  createContext,
  useEffect,
} from "react";
import logo from "./logo.svg";
import "./App.scss";
import Nav from "./components/ui/nav/Nav";
import Welcome from "./components/ui/welcome/Welcome";
import Section from "./components/ux/section/Section";
import Prices from "./components/ui/prices/Prices";
import { themes, ThemeContext } from "./components/theme/theme";
import Background from "./components/ui/background/Background";

function App() {
  const theme = useContext(ThemeContext);
  const [darkmode, setdarkmode] = useState(true);
  const themeMode = themes.light;
  useEffect(() => {
    const themeMode = darkmode ? themes.light : themes.dark;
    console.log(themeMode);
  }, [darkmode]);

  document.body.style.background = theme.primary;
  document.body.style.color = theme.text;
  return (
    <ThemeContext.Provider value={themeMode}>
      <button
        onClick={() => {
          setdarkmode(!darkmode);
        }}
      >
        hello
      </button>
      <Background />

      <Section content={<Welcome />} />
      <Section content={<Prices />} />
    </ThemeContext.Provider>
  );
}

export default App;

这是我的组件之一,应该使用更新后的主题:

import React, { useContext, useState } from "react";
import "./button.scss";
import { themes, ThemeContext } from "../../theme/theme";
export default function Button(props: {
  invert: boolean;
  link: string | URL;
  content: string;
}) {
  var style = {};

  const theme = useContext(ThemeContext);
  const buttonStyle = {
    color: theme.primary,
    background: theme.cta,
    border: "solid 2px " + theme.cta,
  };
  const invertStyle = {
    color: theme.cta,
    background: theme.primary,
    border: "solid 2px " + theme.cta,
  };

  props.invert ? (style = invertStyle) : (style = buttonStyle);
  const [colorStyle, setColorStyle] = useState(false);
  colorStyle
    ? props.invert
      ? (style = buttonStyle)
      : (style = invertStyle)
    : props.invert
    ? (style = invertStyle)
    : (style = buttonStyle);
  return (
    <button
      onClick={() => {
        window.location.assign(props.link);
      }}
      onMouseEnter={() => {
        setColorStyle(!colorStyle);
      }}
      onMouseLeave={() => {
        setColorStyle(!colorStyle);
      }}
      className="ux-btn"
      style={style}
    >
      {props.content}
    </button>
  );
}

您的组件中有 const themeMode = themes.light;。这正是它所说的:将 themeMode 变量设置为常量 themes.light.

当您尝试(我假设)在事件处理程序中“更改它”时,您正在做 const themeMode = darkmode ? themes.light : themes.dark;,但该函数中没有其他任何东西(除了 console.log)-由于此变量仅适用于该函数,因此它不会更改外部的 same-named 变量。

即使你让它改变了外部变量(通过用 let 而不是 const 声明外部变量并且不隐藏函数内部的变量而是更新它的值),那不会'不能很好地与 React 一起工作。

解决方案是改用状态:

  • const themeMode = themes.light替换为const [themeMode, setThemeMode] = useState(themes.light);
  • 在事件处理程序中,将 const themeMode = darkmode ? themes.light : themes.dark; 替换为 setThemeMode(darkmode ? themes.light : themes.dark);

进行上述 2 项更改会奏效 - 但您仍然可以大大简化您的组件。您不需要状态中的 darkModethemeMode,因为一个只是从另一个计算得出的。如果你只使用一个状态变量,你也不需要 useEffect 来根据另一个自动更新一个。但我会让您解决这些问题 - 我希望这至少能帮助您入门!