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},
    },
  });
Daryn
  • 4,791
  • 4
  • 39
  • 52
Shibasis Sengupta
  • 629
  • 1
  • 6
  • 21

7 Answers7

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 :)

tryp
  • 1,120
  • 20
  • 26
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},
  },
});
Thakur Karthik
  • 3,034
  • 3
  • 15
  • 24
  • Thanks, I knew this approach, is there any way to parameterise the backgroundColor inside 'stylesheet.create?' – Shibasis Sengupta Oct 08 '19 at 05:45
  • 2
    @ShibasisSengupta You can export a function that takes parameters, such as bg-color, and return the stylesheet. Example: https://stackoverflow.com/questions/42707327/passing-props-into-external-stylesheet-in-react-native – Sebastian Berglönn Oct 08 '19 at 05:46
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();


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);
gildniy
  • 3,528
  • 1
  • 33
  • 23
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
    }
});
Idan
  • 3,604
  • 1
  • 28
  • 33
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

Erick
  • 1
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>;
}