Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Flow for styled-components Props

So I have been playing around with type systems in JavaScript and for the most part things are working however there is an issue with styled-components. I can't seem to find a good way to apply flow to the props of a styled-component. So far the only solution I see is:

export type ButtonPropTypes = ReactPropTypes & {
  styleType: 'safe' | 'info' | 'warning' | 'danger' | 'link',
  isPill: boolean,
  isThin: boolean,
};

export const ButtonStyled = styled.button`
  ${generateBaseStyles}
  ${hoverStyles}
  ${fillStyles}
  ${thinStyles}
  ${linkStyles}
`;

export const Button = (props: ButtonPropTypes) => <ButtonStyled {...props} />;

It seems pretty excessive that I have to create 2 component for every styled component.

I am hoping my google skills are just crap and I am missing something but is there a better way to do this other than multiple components per styled component?

like image 989
ryanzec Avatar asked Mar 01 '18 01:03

ryanzec


People also ask

Why do I need to separate props and styles?

Because what happens is when the component's Props changes, then the component will re-render and the style will regenerate. Therefore it makes sense to keep it separate. So if you read further on to the Adapting based on props section, they explain this:

What are props in react?

In today's article, we'll talk a little bit about props. Props is a React special keyword that stands for properties and it is used to pass data between components. The styled-component lets you use props and change the CSS with it, as well as do other things that are out of the scope for today.

What is the use of props in CSS?

Properties or props for short, are used to make UI components more dynamic, consider you need two buttons with a different border-color but other CSS properties are the same, you can pass props to each button, with some set of conditions that if that props value is available it should change the CSS property. let’s do this!

What is the use of styled component in react?

The styled-component lets you use props and change the CSS with it, as well as do other things that are out of the scope for today. For instance, if props are "primary" change these colours, so you can dynamically change your button based on anything that you want.


2 Answers

Yes! There is a better way. The trick is to declare the type of the component created by styled-components. You can do this by casting the result returned by styled.button`...` to the type of a React component that takes in your desired props. You can generate the type of a React component that takes in arbitrary props with type mytype = React.ComponentType<MyProps>.

// @flow
import styled from 'styled-components'
// Make sure you import with * to import the types too
import * as React from 'react'

// Mock function to use styleType
const makeStyles = ({styleType}) => ''

export type ButtonPropTypes = {
  styleType: 'safe' | 'info' | 'warning' | 'danger' | 'link',
  isPill: boolean,
  isThin: boolean,
};

export const ButtonStyled = (styled.button`
  ${makeStyles}
  ${({isPill}) => isPill ? 'display: block;' : ''}
  ${({isThin}) => isThin ? 'height: 10px;' : 'height: 100px;'}
`: React.ComponentType<ButtonPropTypes>) // Here's the cast

const CorrectUsage = <ButtonStyled styleType="safe" isPill isThin/>

const CausesError = <ButtonStyled styleType="oops" isPill isThin/> // error

const CausesError2 = <ButtonStyled styleType="safe" isPill="abc" isThin={123}/> // error

I've hosted the code on GitHub for local reproduction (since Flow's sandbox doesn't work with external dependencies): https://github.com/jameskraus/flow-example-of-styled-components-props

like image 105
James Kraus Avatar answered Oct 06 '22 06:10

James Kraus


In addition to James Kraus' answer, if you're using flow-typed (and have installed the package for your version of styled-components) you can essentially:

import styled, {type ReactComponentStyled} from 'styled-components'

type Props = {
 color?: string
}

const Button: ReactComponentStyled<Props> = styled.button`
  color: ${({color}) => color || 'hotpink'};
`
like image 23
Brad Adams Avatar answered Oct 06 '22 08:10

Brad Adams