B. Kwok
B. Kwok

Reputation: 903

React-Native Styled-Components attrs dynamic styles

I'm trying to have my component use dynamic styles in react-native using styled-components. The way to do this is shown here https://github.com/styled-components/styled-components/issues/940

const ColorAnimation = styled.div.attrs({
  style: props => ({
    color: props.color
  })
})`
  // static styles 

It works in React Native as well, as shown here. https://snack.expo.io/ryIXsAe0M

import React, { Component } from 'react';
import { View } from 'react-native';
import styled from 'styled-components/native'; // 2.2.4

const StyledView = styled.View.attrs({
  style: props => ({
    backgroundColor: props.backgroundColor,
    height: props.height,
  }),
})`
  background-color: papayawhip;
`;

const StyledText = styled.Text`
  color: palevioletred;
`;

const RotatedBox = styled.View`
  transform: rotate(90deg);
  text-shadow-offset: 10px 5px;
  font-variant: small-caps;
  margin: 5px 7px 2px;
`;

export default class App extends Component {
  render() {
    return (
      <View style={{ marginTop: 50 }}>
        <StyledView height={100} backgroundColor="yellow">
          <StyledText>Hello World!</StyledText>
        </StyledView>
        <RotatedBox />
      </View>
    );
  }
}

However, I'd rather just pass in a customStyle prop that contains all the dynamic styles I want to use. Like this. . . https://snack.expo.io/BkpToRe0f

const StyledView = styled.View.attrs({
  style: props => props.customStyles,
})`
  background-color: papayawhip;
`;

<StyledView customStyles={{ height: 100, backgroundColor: 'yelllow' }}>

Unfortunately, this does not apply the styles. Does anyone know why this is? Also if there is an alternative solution?

Upvotes: 2

Views: 5293

Answers (3)

Charles Silva
Charles Silva

Reputation: 11

How about trying this

const StyledView = styled(View).attrs(props => ({
    backgroundColor: props.theme.backgroundColor,
    height: props.theme.height,
  })
)

Upvotes: 1

Corbuk
Corbuk

Reputation: 700

For anyone wanting a bit more detailed explanation of when to use additional props in styled components I will make a quick example of how attrs works. Also known as Attaching additional props. You can read about it here on styled components documentation.

Below is a simple example for a background image using CSS. I would need to apply a title and aria-label for accessibility purposes. One way of doing this would be to attach additional props.

// Component
getBackgroundImage = () => {
  const { imageUrl, altTag } = this.props;

  return (
    <BackgroundImage
      imageUrl={imageUrl}
      altTag={altTag}
    />
  );
};

// Styled component
export default styled.div.attrs({
  title: props => props.altTag,
  'aria-label': props => props.altTag,
  role: 'img,
})`
  background: url(${props => props.imageUrl}) center center/ cover no-repeat;
  height: 400px;
  width: 100%;
`;

I would then be able to find this component in the DOM and I would be able to see these attributes. I believe this is the correct usage of this, and separates your concerns regarding additional props and static styling.

In regard to the question:

Unfortunately, this does not apply the styles. Does anyone know why this is?

I believe it's not working as backgroundColor is not an attribute. Height is an attribute that applies to certain HTML elements, which can be found with this link.

Other HTML attributes can be found here

So for your StyledComponent to display correct styles, attrs is not needed.

const StyledView = styled.View`
  background-color: ${props => props.backgroundColor};
  height: ${props => props.height};
`;

<StyledView height={100} backgroundColor="yelllow" />

More information regarding attaching-additional-props and attrs API. They both contain very useful information and examples.

Upvotes: 2

needsleep
needsleep

Reputation: 2715

I think you're a bit confused as to how to use the styled components

This is the example you gave:

const StyledView = styled.View.attrs({
  style: props => ({
    backgroundColor: props.backgroundColor,
    height: props.height,
  }),
})`
  background-color: papayawhip;
`;

And this is how it should be:

const StyledView = styled.View`
  height: ${props => props.height},
  background-color: ${props => props.backgroundColor ? "papayawhip"};
`;

While the first one works as you say, the second one is much cleaner and you can use the component without having to pass an extra customStyles prop. Styled components take care of that for you

<StyledView backgroundColor={"blue"} height="500" />

Upvotes: 0

Related Questions