【问题标题】:how to create context for theme with reactjs?如何使用 reactjs 为主题创建上下文?
【发布时间】:2022-02-03 12:04:03
【问题描述】:

我需要创建一个上下文以在存储库中应用深色或浅色主题。不会通过按钮或类似的东西改变主题,我只是设置主题就可以了

现在,我有这样的上下文

import { createContext } from "react";
import { light } from './themes';

export const ThemeContext = createContext(light);

export default ThemeContext;

还有我的应用

import { light, dark } from './themes';


<ThemeContext.Provider value={light}> // or dark, depending on the project
   <App />   
 </ThemeContext.Provider> 
);

这种方式不行,我该如何应用主题?

【问题讨论】:

  • 如果您想访问ThemeContextProvider 的值,您需要在类组件中使用ThemeContext.Consumer,或者使用const lightTheme = useContext(ThemeContext) 并访问lightTheme 变量中的所有值跨度>

标签: javascript reactjs typescript next.js


【解决方案1】:

您已经创建了一个提供程序,它使其value 可供树中的每个孩子使用。但是,任何想要使用该值的孩子都需要使用它。

如何使用上下文的模式对于类组件 VS 是不同的。函数组件,但基本原理是一样的:你需要告诉你的子组件如何从上下文中获取主题值。

从函数组件中使用上下文

对于函数组件,最简单的方法是使用useContext 钩子(直接从the hooks docs) 复制的示例:

function ThemedButton() {
  const theme = useContext(ThemeContext);
  
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}

带有自定义钩子的有用模式

上述方法可行,但是有一个非常好的模式,您可以将消费者包装在一个自定义挂钩中,您可以称之为useTheme(我第一次看到这种模式here)。

// Step 1
const ThemeContext = React.createContext(undefined)

// Step 2
function ThemeProvider({children}) {
  return (
    <ThemeContext.Provider value={light}>
      {children}
    </ThemeContext.Provider>
  )
}

// Step 3
function useTheme() {
  const context = React.useContext(ThemeContext)
  
  if (context === undefined) {
    throw new Error('useTheme must be used within a ThemeProvider')
  }
  return context
}

export {ThemeProvider, useTheme}

第 1 步 - 创建上下文。你已经在你的例子中做到了。

第 2 步 - 创建提供程序。您在“我的应用”中使用了提供程序。

第 3 步 - 这是新功能。它创建一个自定义钩子,检查提供者是否可访问(如果不是,则抛出错误),然后从提供者返回值。

然后你像这样使用钩子:

function ThemedButton() {
  const theme = useTheme()
  
  return <Text color={theme.textColor}>Some text</Text>
}

这种模式有几个好处:

  1. 您只需要在使用主题的组件中导入钩子useTheme。如果直接使用useContext,则需要导入上下文和useContext钩子。
  2. 如果您不小心尝试在组件树中无权访问提供程序的某个位置使用 useThemethrow new Error('...') 行会向您发出警告。

使用类组件使用上下文

带有类组件的示例有点长且更细微,因此我建议使用the docs 了解如何执行此操作的详细信息。但是,一种方法是这样的:

<ThemeContext.Consumer>
  {value => <ThemedButton theme={value} />
</ThemeContext.Consumer>

【讨论】:

  • 谢谢,我已经可以应用主题了,但是孤立的样式组件,我找不到主题挂钩
  • ````const Container = styled.div` 背景:${({ theme }) => theme.primaryDark}; /错误`;```
  • @ryanMost 您能否在您的问题中添加一个尝试使用theme 的组件示例?这样会更容易提供帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
  • 2021-11-22
  • 2020-01-13
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多