5
4

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 + styled-components で頻出するES6のびっくり記法を冗長に書き直してみる

Last updated at Posted at 2018-11-19

書き直したら読みやすくなるわけでは決してありません!

概要

「constとか、テンプレートリテラルくらいはわかるけど・・・」みたいな方にむけて、今更ではありますがES6の理解を深めるため、ReactのよくあるStateless Functional Componentsを書き直してみます。

例としたコンポーネントはこちらです。

button.js
import React from 'react'
import styled from 'styled-components'
// ↑今後は省略

export default ({
  text = 'Button',
  primary = false
}) => (
  <Wrapper primary={primary}>
    {text}
  </Wrapper>
)

const Wrapper = styled.button`
  padding: 10px;
  ${({ primary }) => primary && `
    background-color: #f99;
    color: #fff;
  `}
  font-size: 12px;
`

アロー関数の簡潔文体

アロー関数においてブロック{}を利用せずに、単一の式だけを記述した場合、その式が明示的に return される値となります。

var func = x => x * x; // x * x の結果が return される

簡潔文体を使わずに書き直すとこうなります。

button.js

export default ({
  text = 'Button',
  primary = false
}) => { // ここ!
  return (
    <Wrapper primary={primary}>
      {text}
    </Wrapper>
  )
}

const Wrapper = styled.button`
  padding: 10px;
  ${({ primary }) => {  // ここ!
    return primary && `
      background-color: #f99;
      color: #fff;
    `}
  }
  font-size: 12px;
`

デフォルト引数

関数に値が渡されない場合や undefined が渡される場合に、デフォルト値で初期化される形式上の引数を指定できます。

function multiply(a, b = 1) {
  return a*b;
}

multiply(5); // 5

大変便利ですが、書き直します。

button.js

export default ({
  text, // ここ!
  primary
}) => {
  text = typeof text !== 'undefined' ? text : 'Button' // ここ!
  primary = typeof primary !== 'undefined' ? primary : false
  return (
    <Wrapper primary={primary}>
      {text}
    </Wrapper>
  )
}

const Wrapper = styled.button`
  padding: 10px;
  ${({ primary }) => {
    return primary && `
      background-color: #f99;
      color: #fff;
    `}
  }
  font-size: 12px;
`

分割代入

分割代入 (Destructuring assignment) 構文は、配列から値を取り出して、あるいはオブジェクトからプロパティを取り出して別個の変数に代入することを可能にする

var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true

これは関数の引数で同じことができます。

button.js
export default (props) => { // ここ!
  var text = typeof props.text !== 'undefined' ? props.text : 'Button'
  var primary = typeof props.primary !== 'undefined' ? props.primary : false
  return (
    <Wrapper primary={primary}>
      {text}
    </Wrapper>
  )
}

const Wrapper = styled.button`
  padding: 10px;
  ${(props) => { // ここ!
    return props.primary && `
      background-color: #f99;
      color: #fff;
    `}
  }
  font-size: 12px;
`

もともとオブジェクトである引数を別個の変数に代入して、扱っていたわけですね。

タグ付けされたテンプレートリテラル

テンプレートリテラルの前に式がある場合、テンプレートリテラルは"タグ付けされたテンプレートリテラル"と呼ばれます。この場合、タグ式(通常は関数)は、処理が完了したテンプレートリテラルと一緒に呼び出され、アウトプットの前に実行できます。

var a = 5;
var b = 10;

function tag(strings, ...values) {
  console.log(strings[0]); // "Hello "
  console.log(strings[1]); // " world"
  console.log(strings[2]); // ""
  console.log(values[0]);  // 15
  console.log(values[1]);  // 50
}

tag`Hello ${ a + b } world ${ a * b}`;

よくわかりませんが、文字列と${}が、それぞれ第1引数の[0][1]...と、第2,3...引数に、交互に渡されるわけなのですね。
というわけで書き直してみます。

(空白や改行を厳密に再現すると大変なので無視しました!)

button.js
export default (props) => {
  var text = typeof props.text !== 'undefined' ? props.text : 'Button'
  var primary = typeof props.primary !== 'undefined' ? props.primary : false
  return (
    <Wrapper primary={primary}>
      {text}
    </Wrapper>
  )
}

const Wrapper = styled.button( // ここ!
  [
    'padding: 10px;',
    'font-size: 12px;'
  ],
  (props) => {
    return props.primary && `
      background-color: #f99;
      color: #fff;
  `}
)

実際に生成されるスタイルもちゃんと下記のようになっていました。

.XXX {
  padding: 10px;
  background-color: #f99;
  color: #fff;
  font-size: 12px;
}

論理演算子(おまけ ES6じゃない)

論理演算子 は、基本的に真偽(論理)値とともに用いられ真偽値を返します。しかし、&& および || 演算子は真偽値ではない値も使うことができるため、その場合は、真偽値ではない値を返すことがあります。

ANDを例にとって解説すると、

論理 AND(&&) a && b a を false と見ることができる場合は、a を返します。そうでない場合は、b を返します。したがって、真偽値と共に使われた場合、 演算対象の両方が true ならば、&& は、true を返し、そうでなければ、false を返します。
true  && true    // t && t true を返します。
true  && false   // t && f false を返します。
false && true    // f && t false を返します。
true && "Dog"    // t && t "Dog" を返します。!!
"Cat" && "Dog"   // t && t "Dog" を返します。!!
0 && false       // f && t 0 を返します。!!
null && true     // f && t null を返します。!!

書き直します。

button.js
export default (props) => {
  var text = typeof props.text !== 'undefined' ? props.text : 'Button'
  var primary = typeof props.primary !== 'undefined' ? props.primary : false
  return (
    <Wrapper primary={primary}>
      {text}
    </Wrapper>
  )
}

const Wrapper = styled.button(
  [
    'padding: 10px;',
    'font-size: 12px;'
  ],
  (props) => {
    if (props.primary) { // ここ!
      return `
        background-color: #f99;
        color: #fff;
      `
    }
    return props.primary
  }
)

まとめ

理解してしまえば、ES6の記法のほうが断然よいですね!

5
4
1

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
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?