33
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React.jsAdvent Calendar 2018

Day 10

Styled Components v4について

Last updated at Posted at 2018-12-09

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が状況に応じて置換されます。

33
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?