I am looking to create a custom component in React Native that will allow me to have different sizes for buttons using react-native-elements
. To achieve this, I created a custom component with a property called size
, which dynamically accesses specific button sizes and their respective styles from the theme
object. Everything is working as expected, but I keep getting the TypeScript error
TS2532: Object is possibly 'undefined'.
every time I try to access the sizes
object within the theme
using bracket notation.
Custom Button Component
import React, { useContext } from 'react';
import { Button, FullTheme, ThemeContext } from 'react-native-elements';
export type Props = Button['props'];
export type Theme = Partial<FullTheme>;
const styles = {
button: (theme: Partial<FullTheme>, size: string) => ({
padding: theme?.Button?.sizes[size]?.padding, // issue here
}),
title: (theme: Partial<FullTheme>, size: string) => ({
fontSize: theme?.Button?.sizes[size]?.fontSize, // issue here
lineHeight: theme?.Button?.sizes[size]?.lineHeight, // issue here
fontFamily: theme?.Button?.font?.fontFamily,
}),
};
function ButtonElement(props: Props): JSX.Element {
const {
size = 'medium',
children,
...rest
} = props;
const { theme } = useContext(ThemeContext);
return (
<Button
titleStyle={styles.title(theme, size)}
buttonStyle={styles.button(theme, size)}
{...rest}
>
{children}
</Button>
);
}
theme.ts
export const theme = {
Button: {
font: {
fontFamily: 'inter-display-bold',
},
sizes: {
small: {
fontSize: 14,
padding: 10,
lineHeight: 20,
},
medium: {
fontSize: 18,
padding: 14,
lineHeight: 24,
},
large: {
fontSize: 20,
padding: 18,
lineHeight: 24,
},
},
},
}
// react-native-elements.d.ts -> Extending the default theme to manage button sizes
import 'react-native-elements';
import { StyleProp, TextStyle } from 'react-native';
export type Sizes = {[index: string]: TextStyle};
export type Size = 'small' | 'medium' | 'large';
declare module 'react-native-elements' {
export interface ButtonProps {
font?: TextStyle;
sizes?: Sizes;
size?: Size;
}
export interface FullTheme {
Button: Partial<ButtonProps>;
}
}
Passing the theme
Object to the Components Tree
// pass theme to the component tree
import { theme } from '@common/styles/theme';
export default function App(): JSX.Element | null {
return (
<ThemeProvider theme={theme}>
<SafeAreaProvider>
<Navigation />
<StatusBar />
</SafeAreaProvider>
</ThemeProvider>
);
}
What I Have Attempted
- I've tried using the
?
operator as suggested in this answer. - I have also explored suggestions mentioned in this post, using
if
statements to ensure thattheme
is not undefined.