【发布时间】:2020-04-22 04:49:21
【问题描述】:
我正在使用 React 上下文来保持全局主题状态。
import React, { useState, createContext } from "react"
const ThemeContext = createContext(localStorage.getItem("theme") || "light")
export const ThemeStore = ({ children }) => {
const [theme, setTheme] = useState(localStorage.getItem("theme") || "light")
const handleThemeChange = theme => {
setTheme(theme)
localStorage.setItem("theme", theme === "dark" ? "dark" : "light")
}
return (
<ThemeContext.Provider value={{ theme, changeTheme: handleThemeChange }}>
{children}
</ThemeContext.Provider>
)
}
export default ThemeContext
我在布局组件中提供此上下文,以便我的整个应用程序可以访问商店。下面是我的布局组件。
import React, { useContext } from "react"
import PropTypes from "prop-types"
import Header from "./header"
import "../styles/layout.css"
import ThemeContext, { ThemeStore } from "../contexts/ThemeContext"
import MobileBottomNav from "../components/mobileBottomNav"
// Wrapper for background color
const Wrapper = ({ children }) => {
const theme = useContext(ThemeContext)
return (
<div className={`${theme.theme === "dark" ? "theme-dark" : "theme-light"}`}>
{children}
</div>
)
}
const Layout = ({ children, hideHeader, hideFooterNavBar }) => {
return (
<ThemeStore>
<Wrapper>
<div className="bg-bg-primary">
<Header hideHeader={hideHeader} />
<main>{children}</main>
<MobileBottomNav hideFooterNavBar={hideFooterNavBar} />
</div>
</Wrapper>
</ThemeStore>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
我的 Header 组件中有一个按钮,可以将主题从浅色更改为深色,反之亦然。我的菜单组件等都改变了颜色,因为我添加了条件类名。
但在我的登录页面中,也包含在提供程序周围,但在状态更改时不会更新。因此,如果我将主题从深色更改为浅色,但它不会重新呈现注册页面,因此颜色不会改变。为什么会这样?如何在主题更改时重新渲染页面以便应用新颜色。
这是我的登录页面。
import React, { useContext } from "react"
import SEO from "../components/seo"
import Layout from "../components/layout"
import ThemeContext from "../contexts/ThemeContext"
const SignInPage = () => {
const theme = useContext(ThemeContext)
// This just logs the initial value of theme, but when I change
// the theme from the header component, this value doesn't log again.
// The component doesn't re-render.
console.log(theme)
return (
<Layout hideFooterNavBar={true}>
<SEO title="Sign In" />
<div>
<div
style={{
paddingTop: "150px",
}}
className="container mx-auto"
>
<p
className={`${
theme.theme === "dark" ? "theme-dark" : "theme-light"
} text-text-primary mb-10`}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In non
sapien blandit, aliquet lorem quis, consectetur tellus. Maecenas ac
nibh eu enim auctor volutpat. Mauris a lacus magna. Proin
sollicitudin mauris sit amet auctor feugiat. Nulla facilisi.
Pellentesque eget massa nec massa porta tristique in vitae ante.
Donec rutrum imperdiet urna.
</p>
</div>
</div>
</Layout>
)
}
export default SignInPage
【问题讨论】:
-
我没有从您发布的代码示例中看到任何异常。你确定你只有 1 个
ThemeContext.Provider,而那个SignupPage是那个ThemeContext.Provider的一个孩子吗?我建议安装 React Devtools chrome 扩展,这样您就可以检查您的组件,并查看上下文提供程序的价值。 -
不仅是注册页面,还有索引页面。两者都由
组件包裹,而 Layout 组件由具有提供程序的 组件包裹。但它不会重新渲染。 -
这里是开发工具的截图。 imgur.com/a/59PSDdJ
标签: javascript reactjs gatsby react-context