1

I wanna create a custom button component that can pass props to the StyleSheet. At this project, the props I wanna send is the hexcode so the component can have different colors based on the color props that are passed to the component. So, I have written this

type Props = {
  backgroundColor: string;
  borderColor: string;
};

export const CustomButton = ({
  backgroundColor,
  borderColor,
}: Props) => {

  return (
    <TouchableOpacity
      style={styles({ backgroundColor, borderColor }).container}
    >
    </TouchableOpacity>
  );

const styles = ({ backgroundColor, borderColor }: Props) =>
  StyleSheet.create({
    container: {
      backgroundColor: backgroundColor,
      borderColor: borderColor,
    },
  });

The idea is to pass the props to the component, and then pass it to the styles on the Touchable component. But, this doesn't work. This always gives me this error on styles({ backgroundColor, borderColor}).container

Argument of type "{ backgroundColor, borderColor }" is not assignable to parameter of type "Props".

So, what went wrong? How am I supposed to pass the props to the StyleSheet?

arahpanah
  • 349
  • 1
  • 6
  • 14

4 Answers4

2

StyleSheet is like a static stuff

You are not supposed to pass argument to it!

All you should do is using an array to pass style

<TouchableOpacity
    style={[styles.container, { backgroundColor, borderColor }]}
>

styles.container is the static part

{ backgroundColor: borderColor } is the dynamic part

type Props = {
  backgroundColor: string;
  borderColor: string;
};

export const CustomButton = ({
  backgroundColor,
  borderColor,
}: Props) => {

  return (
    <TouchableOpacity
      style={[styles.container, { backgroundColor, borderColor }]}
    >
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
    container: {
        // put other style like width, border-radius and etc.
    },
});

If you don't need to set other style, just code like

<TouchableOpacity
    style={{ backgroundColor, borderColor }}
>
TropicsCold
  • 115
  • 6
  • Thanks! Actually, regarding passing the args, I followed this [answer from another SoF post](https://stackoverflow.com/a/51123464/8073417). I'm surprised it got so many upvotes. – arahpanah Jan 19 '21 at 09:52
1

You can do it like this:

<TouchableOpacity
 style={[styles.container, { backgroundColor, borderColor }]}
>
const styles = StyleSheet.create({
 container: {
   // something else style
 },
});
maltoze
  • 717
  • 7
  • 18
  • This gives this error `Property 'container' does not exist on type '({ backgroundColor, borderColor }: Props) => { container: { backgroundColor: string; borderColor: string; }; }'` – arahpanah Jan 19 '21 at 08:01
  • @arahpanah Updated, you don't need to pass props to the `StyleSheet` anymore. – maltoze Jan 19 '21 at 08:06
  • Thanks! It works! Just curious tho, why do we not have pass the value to backgroundColor like `style={[styles.container, { backgroundColor: backgroundColor}]}` – arahpanah Jan 19 '21 at 08:35
  • 1
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#new_notations_in_ecmascript_2015 – maltoze Jan 19 '21 at 08:40
0

return ( <
    TouchableOpacity style = {
      [styles.container, {
          backgroundColor: backgroundColor,
          borderColor: borderColor
        } >
        <
        /TouchableOpacity>
      );

And put some default values on the actual Stylesheet, like:

container: {
  backgroundColor: "#fff",
  borderColor: "#000",
},
0

I know this is an old thread, but I wasn't able to figure it out with the answers in this thread. I was able to get it done by watching some tutorials. So I want to update this thread to hopefully help some other developers who are struggling with this as well.

Let's you have a component like this.

function AppTitle({title, textAlign = "left", marginBottom = 0}) {
    return (
        <Text style={[styles.heading, {textAlign: textAlign, marginBottom: marginBottom}]}>{title}</Text>
    );
}

A stylesheet like this

const styles = StyleSheet.create({
    heading: {
        fontSize: 25,
        fontWeight: "bold",
        textAlign: "left",
        marginBottom: 0,
    },
});

And render the component like this:

<AppTitle title="Some title" textAlign="center" marginBottom={50}/>

Explanation

So in the component you normally add styling by setting the style={styles.your_styles}. If you wrap this in an array, you can pass a second object to overwrite the styles. Like so: style={[styles.your_styles, {backgroundColor: "red"}]}. You can also pass even more objects to the array to overwrite the styles. Keep in mind, it will always use the last style that was provided. So if you use backgroundColor twice, it will use the last backgroundColor provided.

Now in your component you can accept props. function AppTitle({title, textAlign = "left", marginBottom = 0}) {... In this example I destructured them so I can access them easily. I also set a default value for the styles so I don't need to pass them every single time but only if I want something different than the default value.

To overwrite the styles you need to pass the values to the component function. <AppTitle title="Some title" textAlign="center" marginBottom={50}/> In this example the title, textAlign and marginBottom are props that I pass to my component. You can name them to anything you want.

Refilon
  • 3,334
  • 1
  • 27
  • 51