React native elements with Stylesheet.create
Asked Answered
K

7

6

I am trying to use react-native-elements with my React-Native app.

I have a central js file with theme details which are being injected using ThemeProvider as explained here - https://react-native-elements.github.io/react-native-elements/docs/customization.html

However, when I try to use the passed theme in a component's stylesheet.create method, I am getting an error. What am I doing wrong? -

import React from 'react';
import {View, StyleSheet} from 'react-native';
import {Text, withTheme} from 'react-native-elements';

const Header = props => {
  const {theme} = props;

  return (
    <View style={styles.container}>
      <Text>Home</Text>
    </View>
  );
};
const styles = StyleSheet.create({
  container: {
    width: '100%',
    backgroundColor: theme.container.backgroundColor,//**** Getting error here stating that theme is not defined
    shadowRadius: 1.5,
    elevation: 2,
    shadowColor: 'rgb(0,0,0)',
    shadowOpacity: 0.4,
    shadowOffset: {width: 0, height: 2.5},
  },
});

export default withTheme(Header);

Please let me know if I can provide further details.


Update:

Thanks to the suggestion provided below @Sebastian Berglönn , I was able to get it parameterised without exporting to a different file by doing this -

const Header = props => {
  const {theme} = props;

  return (
    <View style={styles(theme).container}>
      <Text>Home</Text>
    </View>
  );
};
const styles = theme =>
  StyleSheet.create({
    container: {
      width: '100%',
      backgroundColor: theme.container.backgroundColor,
      shadowRadius: 1.5,
      elevation: 2,
      shadowColor: 'rgb(0,0,0)',
      shadowOpacity: 0.4,
      shadowOffset: {width: 0, height: 2.5},
    },
  });
Kilgore answered 8/10, 2019 at 5:17 Comment(0)
J
5

I can suggest you a cleaner way using functions with the Stylesheet. The approach is similar to to the suggestion given on the first topic but instead of using a global stylesheet var, we'll use a variable only on the needed style:

  container: theme => ({
      flex: 1,
      backgroundColor: theme.colors.backgroundPrimary
   }),

And on your view, the usage is pretty clean too:

<View style={styles.container(theme)}>

However, both solutions are working like a charm, choose the one which is matching the most with your needs :)

Jaconet answered 21/1, 2020 at 8:40 Comment(2)
This is nice but is not typescript-friendly...Backbend
Creative idea! But cause TypeError in ts. Type '(theme: any) => { color: any; }' is not assignable to type 'ViewStyle | TextStyle | ImageStyle'.ts(2322)Ninny
J
4

From looking the code theme is defined inside the Header Component,So it is showing theme is undefined.

To apply backgroundColor from the theme you can do as follows:

const Header = props => {
  const {theme} = props;

  return (
    <View style={[styles.container,{backgroundColor: theme.container.backgroundColor}]}>
      <Text>Home</Text>
    </View>
  );
};

and don't forget to remove the backgroundColor from StyleSheet.

const styles = StyleSheet.create({
  container: {
    width: '100%',
    //backgroundColor: theme.container.backgroundColor,
    shadowRadius: 1.5,
    elevation: 2,
    shadowColor: 'rgb(0,0,0)',
    shadowOpacity: 0.4,
    shadowOffset: {width: 0, height: 2.5},
  },
});
Jocasta answered 8/10, 2019 at 5:42 Comment(2)
Thanks, I knew this approach, is there any way to parameterise the backgroundColor inside 'stylesheet.create?'Kilgore
@ShibasisSengupta You can export a function that takes parameters, such as bg-color, and return the stylesheet. Example: #42707827Azilian
R
1

Reusable theme solve for react native styles sheet and theme ✅ 😇

I think it help everybody (spent 2 hour for good work of types)


const getStylesHook = <T extends ReturnType<typeof StyleSheet.create>>(
  cb: (theme: IMyTheme) => T,
): (() => {styles: T}) => {
  return () => {
    const theme = useTheme();
    return useMemo(
      () => ({
        styles: cb(theme),
      }),
      [theme.dark],
    );
  };
};

export default getStylesHook;

///

const useStyles = getStylesHook((theme) => ({
   container: {backgroundColor: 'green'}
})

///

const {styles} = useStyles();


Rufina answered 26/4, 2022 at 19:29 Comment(2)
Why do you pass theme to your getStylesHook, eisn't it supposed to receive the style in there?Nolte
See this above is the shit. Just what i needed <3Arborization
S
0

Inside the Provider or children of a Provided component, you can do something like this, by using HOC:

import React from 'react';
import {View, StyleSheet} from 'react-native';
import {Text, withTheme} from 'react-native-elements';

const Header = props => {
  const {theme} = props;

  return (
    <View style={styles(theme).container}> // --> Here styles called as a function
      <Text>Home</Text>
    </View>
  );
};

const styles = theme => StyleSheet.create({
  container: {
      width: '100%',
      backgroundColor: theme.container.backgroundColor,
      shadowRadius: 1.5,
      elevation: 2,
      shadowColor: 'rgb(0,0,0)',
      shadowOpacity: 0.4,
      shadowOffset: {width: 0, height: 2.5},
    }
});

export default withTheme(Header, styles);
Swan answered 28/6, 2021 at 17:20 Comment(0)
H
0

Pass theme to StyleSheet from the style props and use useContext to handle dark/light mode

my code:

const Notifications = (props: NotificationsProps) => {
    const dispatch = useDispatch()
    const theme = useContext(themeContext)
    return (
        <View style={styles(theme).center}>
            <Text style={styles(theme).text}>This is the Notifications screen</Text>
            <Button title="Next" onPress={() => dispatch(setIsOnBoardingDone(true))} />
        </View>
    );
};

const styles = (theme: any) => StyleSheet.create({
    center: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
        textAlign: "center",
        backgroundColor: theme.code_black
    },
    text: {
        color: theme.white
    }
});
Hoarhound answered 15/6, 2022 at 22:41 Comment(0)
B
0

You can use makeStyles hook to reference the theme and props you are using to create the styles.

import React from 'react';
import { Text } from 'react-native';
import { makeStyles } from 'react-native-elements';

type Params = {
  fullWidth?: boolean,
};

const MyComponent = (props: Props) => {
  const styles = useStyles(props);

  return (
    <View style={styles.container}>
      <Text style={{ color: theme.colors.primary }}>Yo!</Text>
    </View>
  );
};

const useStyles = makeStyles((theme, props: Props) => ({
  container: {
    background: theme.colors.white,
    width: props.fullWidth ? '100%' : 'auto',
  },
  text: {
    color: theme.colors.primary,
  },
}));

source: https://reactnativeelements.com/docs/3.4.2/customization#using-the-theme-in-your-own-components

Binion answered 29/9, 2022 at 7:46 Comment(0)
A
0

For anyone having a global theme like I do.

export const useThemedStyleSheet = <T extends ReturnType<typeof StyleSheet.create>>(
  callback: (theme: AOTheme) => T,
): T => {
  const theme = useTheme();
  return useMemo(() => callback(theme), [theme]);
};

Usage

function ComponentWithThemedStyles() {
  const themedStyles = useThemedStyleSheet(theme => ({
    container: {
      backgroundColor: theme.colors.primary,
    },
  }));

  return <View style={themedStyles.container}></View>;
}
Arborization answered 30/8, 2023 at 6:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.