javascript - 用于更改主题的 React Native Context
问题描述
我有一个大约有 6 个屏幕的应用程序,并且想为它们编写一个一致的主题管理器。我觉得我大部分时间都在那里,但我在最后一点挣扎。我想要的是有一个ThemesScreen
包含主题列表,单击每个主题都会动态更改它,我可以看到单击按钮确实会更改名称,但我正在努力让它通过沿着。这是我的ThemeManager.js
:
import React, { createContext, useState } from "react";
import { current } from "../Styles/themes";
export const ThemeContext = React.createContext();
export const ThemeProvider = ({ children }) =>{
//light, dark
const[theme, setTheme] = React.useState("light");
const toggleTheme = () =>{
if(theme === 'light'){
setTheme("dark");
}
else{
setTheme("light");
}
console.log(theme)
}
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
)
}
这是我的ThemesScreen.js
:
import React, { useContext } from 'react';
import { Text, ScrollView, StyleSheet, Alert } from 'react-native';
import { RowItem, RowSeparator } from '../Styles/RowItem';
import ThemeProvider, { ThemeContext } from '../utils/ThemeManager';
function ThemeScreen(){
const theme = useContext(ThemeContext)
return (
<ThemeContext.Consumer>
<ScrollView style={styles.row}>
<RowItem
title="Light theme"
onPress={toggleTheme}/>
<RowSeparator />
<RowItem
title="Dark Theme"
onPress={() => alert('Dark!')}/>
<RowSeparator />
<RowItem
title="Material Blue"
onPress={() => alert('Material blue!')}/>
</ScrollView>
</ThemeContext.Consumer>
)
}
const styles = StyleSheet.create({
row: {
backgroundColor: theme.background,
},
});
export default ThemeScreen
这是我的 Themes.js
export const LightTheme = {
dark: false,
colors: {
primary: 'rgb(255, 45, 85)',
background: 'f5f5f5',
card: 'rgb(255, 255, 255)',
text: '#333333',
border: 'rgba(175, 47, 47, .75)',
notification: 'rgba(175, 47, 47, .35)',
}
}
export const DarkTheme = {
dark: true,
colors: {
primary: 'rgb(255, 45, 85)',
background: 'rgb(0, 0, 0)',
card: 'rgb(255, 255, 255)',
text: 'rgb(28, 28, 30)',
border: 'rgb(199, 199, 204)',
notification: 'rgb(255, 69, 58)',
},
};
const current = LightTheme
export { current }
我最初的想法是,我可以将当前所选主题的名称设置为当前,然后执行以下代码之类的操作,因为我有很多不同的屏幕可以节省我的时间。
import { current } from './styles/themes.js;
...
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: current.background,
paddingTop: 25,
},
但我不太确定如何做到这一点,或者这是否可行。我将不胜感激任何和所有的建议!另外,如果有更好的方法可以做到这一点,请告诉我。
解决方案
您可以将您的移动styles
到组件的主体中:
import { RowItem, RowSeparator } from '../Styles/RowItem';
import ThemeProvider, { ThemeContext } from '../utils/ThemeManager';
function ThemeScreen(){
const theme = useContext(ThemeContext)
const styles = StyleSheet.create({
row: {
backgroundColor: theme.background,
},
});
return (
<ThemeContext.Consumer>
<ScrollView style={styles.row}>
<RowItem
title="Light theme"
onPress={toggleTheme}/>
<RowSeparator />
<RowItem
title="Dark Theme"
onPress={() => alert('Dark!')}/>
<RowSeparator />
<RowItem
title="Material Blue"
onPress={() => alert('Material blue!')}/>
</ScrollView>
</ThemeContext.Consumer>
)
}
export default ThemeScreen
我还建议记住您的切换器和上下文以提高性能。
对于您的react-native
应用程序主题,您是否考虑过使用styled-components
?
我们在我们的跨平台项目中使用它,并添加创建主题化应用程序所需的一切。
它还会将 UX 逻辑从您的组件中分离出来,现在您需要从上下文中手动导入主题,并且您没有像您期望的那样用于样式化组件的 API。
yarn add styled-components
创建一个样式化的组件:
const Container = styled.View(({ theme }) => ({
backgroundColor: theme.colors.white,
}))
添加./theme.js
:
export const theme = {
colors: {
white: '#ffffff',
}
}
并使用您ThemeProvider
的:styled-components/native
App.tsx
+ import { ThemeProvider } from 'styled-components/native'
+ import { theme } from './theme'
- <App />
+ <ThemeProvider theme={theme}><App /></ThemeProvider>
仍然可以使用useTheme()
钩子从组件中访问主题,但我建议您尽量保持样式表逻辑最大程度分离。
推荐阅读
- vb.net - 使用 OAuth 登录的 Google 电子邮件返回 Chimlkat.Imap 的无效凭据
- build - Yocto - 生成所有包含的包的调试符号
- vue.js - 如何使用观察者跟踪计算对象的深层变化
- java - 如何在 android 中从一个列表项移动到另一个列表项?
- python - 使用 g++ 在共享库中包含 Glib::Error 的麻烦
- java - 即使指定的文件具有 ID3 信息,程序也无法从 MP3 文件中找到任何 ID3 信息
- xml - XPath 3.1(不是 XQuery)中有没有办法对结果进行排序?
- bluetooth - 如何在 Linux/Ubuntu 上关闭蓝牙配对?
- c# - 序列化和反序列化不适用于字典作为支持字段
- kubernetes - Kubernetes 更改挂载卷的权限