Help us understand the problem. What is going on with this article?

Styled Components v4について

More than 1 year has passed since last update.

emotionがアツいとのことで、触ってみたい感はすごくあるのですが
ここではStyled Components v4が結構便利なので紹介させていただきたいと思います。

すごく早くて軽くなった

  • 16.1kBから15kB未満に
  • マウント時に約25%の高速化
  • 再レンダリング時に約7.5%の高速化

createGlobalStyle

injectGlobalに代わってcreateGlobalStyleというAPIができました。
通常、styled componentsは自動的にローカルスコープになるため、他のコンポーネントから分離されます。
そこがいいところなのですが、bodyの値とかを一括で変えたいときに困ります。

bodyとかのスタイリングをしたいときにとても便利です。

もともとinjectGlobalというものがありましたが、動的なアップデートやホットリロードが出来なかったり、コンポーネントとして利用できなかったりでした。

import React from 'react';
import styled , { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
  body {
    color: ${props => (props.whiteColor ? 'white' : 'black')};
    background: #333;
  }
`
export default () => <React.Fragment>
  <GlobalStyle whiteColor/>
  Hello React
</React.Fragment>

image.png

"as" prop

styleがあてられたコンポーネントを別のタグで利用したい場合に使います。
.withComponentの代わりとなる機能です。

import React from 'react';
import styled from 'styled-components';

const GrayArea = styled.div`
  background: #333;
  color:white;
`
export default () => <React.Fragment>
  <GrayArea as='button' onClick={() => alert('It works!')}>
    Hello React
  </GrayArea>
</React.Fragment>

GrayAreaはdivとして作られているが、as='button'を使うことでbuttonとして利用できます。

image.png

.extendの廃止

コンポーネントを拡張する場合には、Comp.extendに代わりstyled(Comp)と記述するように統一されました。

import React from 'react';
import styled from 'styled-components';

const Button = styled.button`
  background: #333;
  color: white;
`

const RedButton = styled(Button)`
  background: red;
`

export default () => <React.Fragment>
  <RedButton  onClick={() => alert('It works!')}>
    Hello React
  </RedButton>
</React.Fragment>

image.png

Strict Modeへの完全対応

Strict Modeに準拠する形になっています。

refのネイティブサポート

innerRefが廃止されたことによる対応です。

import React from 'react';
import styled from 'styled-components';

const Input = styled.input`
  padding: 0.5em;
  background: #333;
  color: white;
`

export default class Form extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }

  render() {
    return (
      <Input
        ref={this.inputRef}
        placeholder="Hover to focus!"
        onMouseEnter={() => {
          this.inputRef.current.focus()
        }}
      />
    );
  }
}

image.png

css prop

いちいちコンポーネントを作るのが面倒な場合に、以下のように書けるようになりました。
babel pluginが必要で、実際には下のように変換されます。

<div
  css={`
    background: papayawhip;
    color: ${props => props.theme.colors.text};
  `}
/>
<Button
  css="padding: 0.5em 1em;"
/>
const StyledDiv = styled.div`
  background: papayawhip;
  color: ${props => props.theme.colors.text};
`

const StyledButton = styled(Button)`
  padding: 0.5em 1em;
`

<StyledDiv />
<StyledButton />

Theme Consumer

Context APIのConsumerコンポーネント。
ThemeProviderにて注入された状態を利用したConsumerが作成できるようになりました。

import React from 'react';
import styled, { ThemeProvider , ThemeConsumer} from 'styled-components';

const Child = () => <div>
  <ThemeConsumer>
    {theme => <div>The theme color is {theme.color}.</div>}
  </ThemeConsumer>
</div>

export default () => <ThemeProvider theme={{ color: 'black' }}>
  <Child/>
</ThemeProvider>

image.png

移行について

以前のバージョンを利用している場合、codemodsを利用して変換を行うことができます。

グローバルインストールして

npm install -g styled-components-codemods

コマンドを叩く

styled-components-codemods v4 src/**/*.js

Comp.extendinjectGlobalが状況に応じて置換されます。

7tsuno
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away