On This Page

  • Basics
  • Attaching additional props

Attaching additional props

To avoid unnecessary wrappers that just pass on some props to the rendered component, or element, you can use the .attrs constructor. It allows you to attach additional props (or "attributes") to a component.

This way you can for example attach static props to an element, or pass a third-party prop like activeClassName to React Router's Link component. Furthermore you can also attach more dynamic props to a component. The .attrs object also takes functions, that receive the props that the component receives. The return value will be merged into the resulting props as well.

Here we render an Input component and attach some dynamic and static attributes to it:

const Input = styled.input.attrs((props) => ({
  // we can define static props
  type: 'text',
  // or we can define dynamic ones
  size: props.size || 'small',
}))(/* */)
 
render(
  <div>
    <Input placeholder="A small text input" />
    <br />
    <Input placeholder="A bigger text input" size="2em" />
  </div>
)

As you can see, the type attribute is passed down to the element. It also allows you to set variants of your component or any other dynamic property.

Overriding .attrs

Notice that when wrapping styled components, .attrs are applied from the innermost styled component to the outermost styled component.

This allows each wrapper to override nested uses of .attrs, similarly to how css properties defined later in a stylesheet override previous declarations.

Input's .attrs are applied first, and then PasswordInput's .attrs:

const Input = styled.input.attrs((props) => ({
  type: 'text',
  size: props.size || 'small',
}))(/* */)
 
// Input's attrs will be applied first, and then this attrs obj
const PasswordInput = styled(Input).attrs({
  type: 'password',
})(/**/)
 
render(
  <div>
    <Input placeholder="A bigger text input" size="2em" />
    <br />
    {/* Notice we can still use the size attr from Input */}
    <PasswordInput placeholder="A bigger password input" size="2em" />
  </div>
)

This is why PasswordInput is of a password type, but still uses the size attribute from Input.