LoginSignup
17
16

More than 5 years have passed since last update.

Reactでいいねボタン

Last updated at Posted at 2016-06-24

どなたかが書かれていた気もしますが、30分間React入門「いいねボタン」作成チュートリアルというものを勉強がてら写経してみました。
途中、いくつかつまづいたとこもあったので備忘録として書きたいと思います。

途中に補足のようなことが書いてありますが、自分でもよくわかっていないので間違っていることなどあればご指摘いただけると助かります。
(ここに書いてあることはほとんど30分間React入門「いいねボタン」作成チュートリアルに書いてありますのでまずはそちらを御覧ください。)

導入

まずはいろいろインストールしていきます。
本家ではbabel-coreがインストールされておらずエラーが出ていたので忘れずにインストールしましょう。

$ npm init
$ npm install --save-dev webpack babel-loader babel-core
$ touch webpack.config.js
webpack
Webアプリに必要なリソースの依存関係を解決してくれるビルドツールです。Reactを使うには必須のアイテムです。似たツールにBrowserifyなどがあります。JavaScriptだけでなく、CSS系(Sass, LESS, stylus)、画像ファイルなども扱うことができます。
babel
ECMAScriptコンパイラです。ECMAScript2015(ES6)やECMAScript2016(ES7)などをブラウザがサポートしているES5形式に出力してくれます。

詳しい解説は下記リンクからどうぞ。

続いてwebpackの設定を記述していきます。
これも本家では古い書き方になっていてECMAScript2015だとエラーが出るので書き直しました。

参考:webpack+babel環境でフロントエンドもES6開発

webpack.config.js
module.exports = {
    entry: __dirname + "/src/main.js",
    output: {
        path: __dirname + "/dist",
        filename: "like-button.js"
    },
    module: {
        loaders: [{
            test: /\.js$/,
            loader: "babel",
            query: {
                presets: ["react", "es2015", "stage-0"] //react入れないとエラー出るよ&書き方がES2015だと違うよ
            }
        }]

    }
};

ソースコードとビルドされたJSが入るディレクトリを作成します。

$ mkdir src dist
$ touch ./src/main.js
$ touch dist/index.html

package.jsonにwebpackのビルドタスクを定義します。

{
...
  "scripts": {
    ...
    "build": "rm -rf dist/*.js && webpack",
    "watch": "rm -rf dist/*.js && webpack -w"
  },
...
}

Reactインストール

npm install --save react react-dom

HTML

まず、骨組みとなるHTMLをdist配下に作ります。

index.html
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>デモ</title>
  <script src="like-button.js"></script>
</head>
<body>
  <div id="like-button"></div>
</body>
</html>

React

メインのReactを書いていきます。

今回、CSSはReactの中にオブジェクトのような感じで書いていきます。
巷ではCSS in JSとか言われており、新しいアプローチとして注目を浴びてるらしいです。

main.js
import React from "react";
import ReactDom from "react-dom";

//コンポーネント定義

class LikeButton extends React.Component {
  constructor(props) {
    super(props);

//ホバーの状態、カウント数、Likeの有無をstateで定義

    this.state = {
      hovered: false,
      count: 999,
      liked: false
    }
  }
  styles() {
    return {
      container: {
        fontFamily: "helvetica, arial, 'hiragino kaku gothic pro', meiryo, 'ms pgothic', sans-serif",
        fontSize: 11
      },
      like: {
        display: "inline-block",
        background: "#3b5998",
        padding: "0px 5px",
        borderRadius: 2,
        color: "#ffffff",
        cursor: "pointer",
        float: "left",
        height: 20,
        lineHeight: "20px"
      },
      likeHover: {
        background: "#444"
      },
      counterBefore: {
        display: "block",
        float: "left",
        width: 6,
        height: 6,
        background: "#fafafa",
        marginLeft: "-12px",
        borderRight: 10,
        transform: "rotate(45deg)",
        WebkitTransform: "rotate(45deg)",
        marginTop: 6,
        borderLeft: "1px solid #aaa",
        borderBottom: "1px solid #aaa"
      },
      counter: {
        display: "block",
        background: "#fafafa",
        boxSizing: "border-box",
        border: "1px solid #aaa",
        float: "left",
        padding: "0px 8px",
        borderRadius: 2,
        marginLeft: 8,
        height: 20,
        lineHeight: "20px"
      }
    };
  }

//マウスホバーのイベントハンドラ

  onMouseEnter() {
    this.setState({hovered: true});
  }

  onMouseLeave() {
    this.setState({hovered: false});
  }

//クリックのイベントハンドラ

  onClick(){
    this.setState({
      count: this.state.count + (this.state.liked ? -1 : 1),
      liked: !this.state.liked
    });
  }

  render() {
    const styles = this.styles();

//ホバーの判定からのスタイル変更
//{...styles.like, ...styles.likeHover}はES7でふたつのオブジェクトをマージする構文

    const likeStyle = this.state.hovered ? {...styles.like, ...styles.likeHover} : styles.like;

    return (
      <span style={styles.container}>
        <span
          style={likeStyle}
          onMouseEnter={::this.onMouseEnter}
          onMouseLeave={::this.onMouseLeave}
          onClick={::this.onClick}>{this.state.liked ? "" : ""}いいね</span>
        <span style={styles.counter}>
          <span style={styles.counterBefore}>{" "}</span>
          {this.state.count}
        </span>
      </span>
    );
  }
}

ReactDom.render(
  <LikeButton / >, document.getElementById("like-button"));

おわりに

Reactを最近やり始めて、なんとなくコンポーネントのことやstate, propsのことがわかってきた気がします。
CSSをJSの中に書くのは初めてだったけど、Reactと一緒に使うと動的にCSSを適用することができて非常に便利だと感じました。

17
16
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
17
16