I need to create a context to apply dark or light theme in repositories. There will be no change of themes by button or something like that, I'll just set the theme and that's it
for now, I have context like this
import { createContext } from "react";
import { light } from './themes';
export const ThemeContext = createContext(light);
export default ThemeContext;
and my app
import { light, dark } from './themes';
<ThemeContext.Provider value={light}> // or dark, depending on the project
<App />
</ThemeContext.Provider>
);
that way is not working, how can I apply the theme?
I need to create a context to apply dark or light theme in repositories. There will be no change of themes by button or something like that, I'll just set the theme and that's it
for now, I have context like this
import { createContext } from "react";
import { light } from './themes';
export const ThemeContext = createContext(light);
export default ThemeContext;
and my app
import { light, dark } from './themes';
<ThemeContext.Provider value={light}> // or dark, depending on the project
<App />
</ThemeContext.Provider>
);
that way is not working, how can I apply the theme?
Share Improve this question asked Feb 3, 2022 at 1:44 ryan Mostryan Most 411 silver badge3 bronze badges 1-
2
If you want to access the value of the
ThemeContextProvider
you need to either useThemeContext.Consumer
in class ponents, or theconst lightTheme = useContext(ThemeContext)
and access all the values from thelightTheme
variable – Ameer Commented Feb 3, 2022 at 1:57
1 Answer
Reset to default 4You've created a provider which makes its value
available to every child in the tree. But, any child that wants to use that value needs to consume it.
The patterns for how to consume the context are different for class ponents VS. function ponents but the basic principle is the same: you need tell your child ponent how to get the theme value from the context.
Consuming Context from a function ponent
For function ponents, the simplest way is with the useContext
hook (example copied straight from 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>
);
}
A helpful pattern with a custom hook
The above works, but there's a really nice pattern where you can wrap the consumer in a custom hook which you'd call something like useTheme
(I first saw this pattern 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}
Step 1 - Creates the context. You've already done this in your example.
Step 2 - Creates the provider. You've used a provider in "my app".
Step 3 - This is what's new. It creates a custom hook that checks that the provider is accessible (throwing an error if not) and then returns the value from the provider.
You then use the hook like this:
function ThemedButton() {
const theme = useTheme()
return <Text color={theme.textColor}>Some text</Text>
}
There are a few benefits to this pattern:
- You only need to import the hook,
useTheme
, in the ponents that consume the theme. If you useuseContext
directly, you need to import the context and theuseContext
hook. - The
throw new Error('...')
line will warn you if you accidentally try to useuseTheme
somewhere in the ponent tree that doesn't have access to the provider.
Consuming Context with a class ponent
The examples with class ponents are a little long and more nuanced, so I'll remend using the docs for the details of how to do that. But, one approach is like this:
<ThemeContext.Consumer>
{value => <ThemedButton theme={value} />
</ThemeContext.Consumer>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745396487a4625902.html
评论列表(0条)