Styled Components for React Native the way they should have been
source link: https://reactnativeexample.com/styled-components-for-react-native-the-way-they-should-have-been/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
💄 Styled-RN
Styled Components for React Native the way they should have been.
Inspired by this article
Intro
Why 💄 styled-rn
it better than 💅🏼 styled-components/native
?
Well, first of all, using styled components should be fun, but using css to style a React Native app is cumbersome and often ends up to be very messy.
Also:
styled-rn
gives you access to ALL React Native style propsstyled-rn
is faster because it does not do tedious string template processingstyled-rn
is easier to use (again, no messy string templates)styled-rn
is fully typed and has a nice APIstyled-rn
supports custom props, theme viaThemeProvider
, multiple style objects and more..styled-rn
has a shorter name 😉
Usage:
npm i styled-rn
import { styled } from "styled-rn"; // Basic usage export const Container = styled.View({ flexDirection: "row", backgroundColor: "cyan", }); // Use with any component export const CoolAndBoldComponent = styled(CoolComponent, { fontWeight: "bold", });
Theming:
You will need to do a few things in order to propagate the theme
prop into all of your styled components:
- Define your theme object and the type for it
- Augment the
Theme
type - Wrap your app in
ThemeProvider
First, define your theme:
// mytheme.ts export const theme = { primary: "blue", background: "white", ... } as const; export type MyAppTheme = typeof theme;
TODO: add example on how to use multiple themes
Now you need to augment the default Theme
type with your own type. In order to do that, create a definitions file at the root of your source tree (e.g. global.d.ts
) and add the following to it:
import { MyAppTheme } from './mytheme.ts' declare module 'styled-rn' { // eslint-disable-next-line @typescript-eslint/no-empty-interface interface Theme extends MyAppTheme {} }
And finally, the wrapping, as usual:
// App.tsx import { ThemeProvider } from 'styled-rn'; import { theme } from './mytheme.ts'; export default function App() { return ( <ThemeProvider theme={theme}> { /* your app components */} </ThemeProvider> ) }
And that’s it! You can now access your theme in any styled component:
export const Button = styled.TouchableOpacity( ({ theme }) => ({ backgroundColor: theme.background, }) );
If you want to use custom props in your styled component, make sure that your custom props interface extends ThemedProps
. E.g.
// Important: 👇 interface ButtonProps extends ThemedProps { disabled?: boolean; } export const Button = styled.TouchableOpacity( ({ disabled, theme }: ButtonProps) => ({ opacity: disabled ? 0.3 : 1, backgroundColor: theme.background, }) ); // Using conditional styles with custom props interface SmartComponentProps extends ThemedProps { active?: boolean; } export const SmartComponent = styled.TouchableOpacity( ({ active, theme }: SmartComponentProps) => [ { fontSize: 16, }, active && { fontWeight: theme.activeFontWeight, color: theme.activeColor, }, ] );
You can also use theme
in your components by calling the useTheme()
hook or by wrapping your component with withTheme()
HOC.
import { useTheme } from 'styled-rn'; export const MyComponent = () => { const theme = useTheme(); }
Advanced Topics
TODO:
- useDebugStyles: per component and globally
- theme: rootStyles, rootFont, rootBackgroundColor, etc..
Issues
- BUG: When component returns the style from inline function sometimes the style object has to be type casted to ViewStyle, TextStyle, etc… Otherwise, you’ll get a weird TS error. It looks like a TS bug.
If you don’t want to cast your styles, make sure that you pass props to the function and USE THE PROPS in your styles.
TODO:
Feature Compare with:
- Add typescript tests
- Add react tests (expect componets with specific styles), test theme nesting, etc…
- Add more examples: Button (View with Text), using functions to generate styles.
- Add support for presets? I.e. platform independant styles? E.g.:
elevation: (value) => ({ shadowColor: 'black', shadowOffset: { width: 0, height: value }, shadowRadius: value * 2.5, shadowOpacity: 0.3, elevation: value, zIndex: value, }),
Presets can use Platform, Dimensions, etc..
E.g.: ...Platform.select({ ios { width: 100 }, android: { width: 75 } })
See example here
GitHub
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK