React Native(或React)在单独的ts模块中监听暗模式的样式变化
React Native (or React) listen to the style changes for the dark mode in separate ts modules
目标:在 React Native 应用程序中实现 暗模式。
系统简介:
文件结构:
- Profile.ts
- ProfileCss.ts
- constants.ts
在我的应用程序中,为了将样式与组件分开,我将它们移动到 .ts 文件中并导出为模块。
StyleCss.ts的示例:
import {StyleSheet} from 'react-native';
import {Window, FixedCSS, hsize, wsize} from '../../entities/constants';
export default StyleSheet.create({
loading: {
backgroundColor: FixedCSS.Colors.MainBackgroundColor,
}
...
});
存储在 constants.ts 中的所有与样式相关的常量值,例如颜色、行高等。还有 constants.ts 包含一个名为 FixedCSS 的 class,它具有静态属性:
export class FixedCSS {
static isDark = true;
static Colors = {
// Main Colors
RootColor: FixedCSS.isDark ? '#FF6666' : '#FF6666',
MainBackgroundColor: FixedCSS.isDark ? '#050505' : '#FFFFFF',
...
}
...
}
isDark 属性 FixedCSS 应该借助 Profile.ts
中的 Switch 组件进行更改
<Switch
value={darkMode}
onValueChange={value => {
this.setState({darkMode: value});
}}
/>
问题:如何修改FixedCSS class中的isDark属性,这样会影响组件的外观。最有问题的方面是 StyleCSS.ts 文件不会反映 FixedCSS class 中 isDark 属性 的变化,因为它们仅在以下情况下导出一次js 包被创建。
更改 class 的 static
属性 不会触发重新呈现的方式。这需要以某种方式利用 state
。我推荐一个主题Context
。您可以使用一个上下文或单独的上下文来控制 isDarkMode
并提供 CSS,这就是我在这里所做的。
为了仅导出一个值一次并使该值保持最新,导出的值可以是函数而不是常量。我正在使固定 CSS 成为 isDark
的函数,并且各个组件样式成为 FixedCSS
.
的函数
constants.ts
export const createFixedCSS = (isDark: boolean) => ({
isDark,
Colors: {
// Main Colors
RootColor: isDark ? "#FF6666" : "#FF6666",
MainBackgroundColor: isDark ? "#050505" : "#FFFFFF"
...
}
...
});
export type FixedCSS = ReturnType<typeof createFixedCSS>;
export const IS_DARK_DEFAULT = false;
cssContext.ts
// context to provide the FixedCSS object, which also includes isDark
const FixedCSSContext = createContext(createFixedCSS(IS_DARK_DEFAULT));
// context to provide a function for switching modes
// type Dispatch<SetStateAction<T>> allows for setting based on previous value
type SetModeContextValue = Dispatch<SetStateAction<boolean>>;
// needs an initial value that fits the type signature
const SetModeContext = createContext<SetModeContextValue>(() => {
throw new Error(
"cannot set `isDark` outside of a `DarkModeContext` Provider"
);
});
// combine both contexts into one Provider component
export const CSSProvider: FC<{}> = ({ children }) => {
// store the isDark state
const [isDark, setIsDark] = useState(IS_DARK_DEFAULT);
// update the FixedCSS when isDark changes
// I'm not sure if memoizing is actually necessary here?
const FixedCSS = useMemo(() => createFixedCSS(isDark), [isDark]);
return (
<SetModeContext.Provider value={setIsDark}>
<FixedCSSContext.Provider value={FixedCSS}>
{children}
</FixedCSSContext.Provider>
</SetModeContext.Provider>
);
};
// I prefer to export the hooks rather than the contexts themselves
export const useFixedCSS = () => useContext(FixedCSSContext);
export const useSetMode = () => useContext(SetModeContext);
// helper hook for `StyleCss.ts` files
// takes the makeStyles factory function and turns it into a style object by accessing the FixedCSS context
export const useStyleFactory = <T extends StyleSheet.NamedStyles<T>>(
factory: (css: FixedCSS) => T
): T => {
const FixedCSS = useFixedCSS();
return useMemo(() => factory(FixedCSS), [FixedCSS, factory]);
};
ProfileCss.ts
export const makeStyles = (FixedCSS: FixedCSS) => StyleSheet.create({
loading: {
backgroundColor: FixedCSS.Colors.MainBackgroundColor,
}
});
Profile.ts
const DarkModeToggle = () => {
// access isDark from global FixedCSS
const {isDark} = useFixedCSS();
// access update callback
const setIsDark = useSetMode();
return (
<Switch
value={isDark}
onValueChange={setIsDark}
/>
)
}
const Profile = () => {
// pass the imported `makeStyles` to the hook and get stateful styles object
const styles = useStyleFactory(makeStyles);
return (
<View>
<DarkModeToggle/>
<View style={styles.loading}/>
</View>
);
};
CodeSandbox Demo(全部在一个文件中)
目标:在 React Native 应用程序中实现 暗模式。 系统简介: 文件结构:
- Profile.ts
- ProfileCss.ts
- constants.ts
在我的应用程序中,为了将样式与组件分开,我将它们移动到 .ts 文件中并导出为模块。 StyleCss.ts的示例:
import {StyleSheet} from 'react-native';
import {Window, FixedCSS, hsize, wsize} from '../../entities/constants';
export default StyleSheet.create({
loading: {
backgroundColor: FixedCSS.Colors.MainBackgroundColor,
}
...
});
存储在 constants.ts 中的所有与样式相关的常量值,例如颜色、行高等。还有 constants.ts 包含一个名为 FixedCSS 的 class,它具有静态属性:
export class FixedCSS {
static isDark = true;
static Colors = {
// Main Colors
RootColor: FixedCSS.isDark ? '#FF6666' : '#FF6666',
MainBackgroundColor: FixedCSS.isDark ? '#050505' : '#FFFFFF',
...
}
...
}
isDark 属性 FixedCSS 应该借助 Profile.ts
中的 Switch 组件进行更改<Switch
value={darkMode}
onValueChange={value => {
this.setState({darkMode: value});
}}
/>
问题:如何修改FixedCSS class中的isDark属性,这样会影响组件的外观。最有问题的方面是 StyleCSS.ts 文件不会反映 FixedCSS class 中 isDark 属性 的变化,因为它们仅在以下情况下导出一次js 包被创建。
更改 class 的 static
属性 不会触发重新呈现的方式。这需要以某种方式利用 state
。我推荐一个主题Context
。您可以使用一个上下文或单独的上下文来控制 isDarkMode
并提供 CSS,这就是我在这里所做的。
为了仅导出一个值一次并使该值保持最新,导出的值可以是函数而不是常量。我正在使固定 CSS 成为 isDark
的函数,并且各个组件样式成为 FixedCSS
.
constants.ts
export const createFixedCSS = (isDark: boolean) => ({
isDark,
Colors: {
// Main Colors
RootColor: isDark ? "#FF6666" : "#FF6666",
MainBackgroundColor: isDark ? "#050505" : "#FFFFFF"
...
}
...
});
export type FixedCSS = ReturnType<typeof createFixedCSS>;
export const IS_DARK_DEFAULT = false;
cssContext.ts
// context to provide the FixedCSS object, which also includes isDark
const FixedCSSContext = createContext(createFixedCSS(IS_DARK_DEFAULT));
// context to provide a function for switching modes
// type Dispatch<SetStateAction<T>> allows for setting based on previous value
type SetModeContextValue = Dispatch<SetStateAction<boolean>>;
// needs an initial value that fits the type signature
const SetModeContext = createContext<SetModeContextValue>(() => {
throw new Error(
"cannot set `isDark` outside of a `DarkModeContext` Provider"
);
});
// combine both contexts into one Provider component
export const CSSProvider: FC<{}> = ({ children }) => {
// store the isDark state
const [isDark, setIsDark] = useState(IS_DARK_DEFAULT);
// update the FixedCSS when isDark changes
// I'm not sure if memoizing is actually necessary here?
const FixedCSS = useMemo(() => createFixedCSS(isDark), [isDark]);
return (
<SetModeContext.Provider value={setIsDark}>
<FixedCSSContext.Provider value={FixedCSS}>
{children}
</FixedCSSContext.Provider>
</SetModeContext.Provider>
);
};
// I prefer to export the hooks rather than the contexts themselves
export const useFixedCSS = () => useContext(FixedCSSContext);
export const useSetMode = () => useContext(SetModeContext);
// helper hook for `StyleCss.ts` files
// takes the makeStyles factory function and turns it into a style object by accessing the FixedCSS context
export const useStyleFactory = <T extends StyleSheet.NamedStyles<T>>(
factory: (css: FixedCSS) => T
): T => {
const FixedCSS = useFixedCSS();
return useMemo(() => factory(FixedCSS), [FixedCSS, factory]);
};
ProfileCss.ts
export const makeStyles = (FixedCSS: FixedCSS) => StyleSheet.create({
loading: {
backgroundColor: FixedCSS.Colors.MainBackgroundColor,
}
});
Profile.ts
const DarkModeToggle = () => {
// access isDark from global FixedCSS
const {isDark} = useFixedCSS();
// access update callback
const setIsDark = useSetMode();
return (
<Switch
value={isDark}
onValueChange={setIsDark}
/>
)
}
const Profile = () => {
// pass the imported `makeStyles` to the hook and get stateful styles object
const styles = useStyleFactory(makeStyles);
return (
<View>
<DarkModeToggle/>
<View style={styles.loading}/>
</View>
);
};
CodeSandbox Demo(全部在一个文件中)