読者です 読者をやめる 読者になる 読者になる

Reactでいいねボタン

このページを写経してみました。
ちょっとわかった気がするReact

導入

$ npm init
//babel-coreがないとだめ
$ npm install --save-dev webpack babel-loader babel-core
$ touch webpack.config.js

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だと違うよ
            }
        }]

    }
};
$ 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

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"));

index.html

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Reactで作った「いいねボタン」のデモ (Flux不使用)</title>
</head>
<body>
  <h1>Reactで作った「いいねボタン」のデモ (Flux不使用)</h1>
  <div id="like-button"></div><!-- ここにコンポーネントをマウント -->
  <script src="like-button.js"></script>
</body>
</html>