当响应上下文变量更改时,页面不会重新呈现

时间:2020-01-03 16:04:58

标签: javascript reactjs gatsby react-context

我正在使用React上下文来保持全局主题状态。

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

我正在布局组件中提供此上下文,以便我的整个应用程序都可以访问商店。下面是我的布局组件。

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

Header组件中有一个按钮,可将主题从浅色更改为深色,反之亦然。我的菜单组件等都改变了它们的颜色,因为我添加了条件类名。

但是在我的登录页面中,状态更改时,该页面也被包裹在提供者周围,但不会更新。因此,如果我将主题从暗改为亮,但不会重新渲染注册页面,因此颜色也不会改变。为什么会这样呢?主题更改后如何重新渲染页面,以便应用新的颜色。

这是我的登录页面。

UpdateAtrribute

1 个答案:

答案 0 :(得分:1)

您的问题是,您在ThemeContext的下方消费ThemeContext.Provider

如果您检查React devtools,您应该看到您的树看起来像这样:

  • 登录页面
    • 布局
      • ThemeStore
      • ThemeContext.Provider
        • 包装器

相反,您可以做的是在Layout子级组件中使用上下文,或者使用更高阶的组件将ThemeContext注入SignInPage中:

const SignInPage = ({ theme }) => {
  // ...
}

export default props => (
  <ThemeContext.Consumer>
    {theme => 
      <SignInPage theme={theme} {...props} />
    }
  </ThemeContext.Consumer>
)