tlog

主にシステム開発とプログラミングについて

React.jsでonClickイベントを利用する場合の注意点

はまったのでメモ。

React.jsでBootstrapのテンプレートなどを利用する場合、offcanvasを利用するためにjQueryなどでonclickイベントを下記のように登録すると思います。

<a href="#" className="sidebar-toggle" data-toggle="offcanvas" role="button">

みたいなリンクにjQueryで登録する場合、

$(toggleBtn).on('click', function (e) {
  e.preventDefault();
  //hogehoge
});

しかし、React.jsは独自のイベント管理してるらしく、下記のようにコンポーネント自体に登録してあげないと上手く動きません。

<Button bsStyle="success" bsSize="small" onClick={someCallback}>
  Something
</Button>

下記にきちんと書かれてました。 もちろん本家のReact.jsページにも…

React-Bootstrap

Eclipse ScalaIDEでBuild時に.gitignoreに/scala/が勝手に追加された時の対処法

先日ハマったので、備忘録として…

Eclipse LunaでScalaIDEを利用してビルドしている時に、.gitignoreへ/scala/が勝手に追加されました。 しかも1行ではなく複数行も…

対処法を検索して見ましたが、とくに見当たらず… 結果、ScalaIDEが悪いわけではなく、Eclipseの下記の設定を外すことで回避することができました。

英語:Window → Preferences → Team → Git → Projects → Automatically ignore derived resources .. setting.

日本語:ウィンドウ -> 設定 ->チーム -> Git -> プロジェクト -> Automatically ignore derived resources by adding them to .gitignore

参考にしたのは下記サイトです。

eclipse - Are gitignore files being automatically created in my project? - Stack Overflow

Git version control with Eclipse (EGit) - Tutorial

ReactとScala.jsで簡単なプロジェクトを作成してみました

facebookが開発しているReactを使ってみたくて、どうせならAltJSであるScala.jsですべて実装しようと思いましたが、少々Scala.jsのReact実装が現時点では使いづらかったので、View層を素のReactで、サーバとの通信をScala.jsで実装したサンプルプロジェクトを作成してみました。

Reactのクライアントから、Scala.jsでjavascriptへ変換されたAjax APi(autowire)を用いてサーバとJsonデータを透過的にやり取りしています。

https://github.com/MomoPain/scalajs-react-crud

プロジェクトの構成は、Scala.jsのCrossProjectを用いています。

-shard(クライアントとサーバで利用するコード:モデルとデータ通信API)

-client(Scala.jsでjavascriptに変換されるデータ通信API)

-server(autowireのサーバサイド実装、Scalatraでjsonデータを受け付けている)

クライアントであるView層は、Reactのチュートリアルであるコメント情報をCRUD操作するアプリケーションを参考にしています。

var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment key={comment.key} index={comment.key}author={comment.author} comment={comment.text}>
          
        </Comment>
      );
    });
    return (
    <table className="table">
        <thead>
        <th>#</th>
        <th>Name</th>
        <th>Comment</th>
        </thead>
        <tbody>
        {commentNodes}
        </tbody>
    </table>
    );
  }
});

var CommentForm = React.createClass({
    handleSubmit: function(e) {
        e.preventDefault();
        var author = React.findDOMNode(this.refs.author).value.trim();
        var text = React.findDOMNode(this.refs.text).value.trim();
        if (!text || !author) {
          return;
        }
        this.props.onCommentSubmit({author: author, text: text});
        React.findDOMNode(this.refs.author).value = '';
        React.findDOMNode(this.refs.text).value = '';
        return;
      },
      render: function() {
        return (
        <form className="form-inline" onSubmit={this.handleSubmit}>
          <div className="form-group">
            <input type="text" className="form-control" ref="author" placeholder="Your Name"/>
          </div>
          <div className="form-group">
            <input type="text" className="form-control" ref="text" placeholder="Say someting..."/>
          </div>
          <button type="submit" className="btn btn-success">Post</button>
        </form>
    
        );
      }
    });


var CommentBox = React.createClass({
      loadCommentsFromServer: function() {
          //call ajax api that is generated from scala.js
          client.CommentAction().list(this);
      },
      handleCommentSubmit: function(comment) {
          // call ajax api that is generated from scala.js
          client.CommentAction().update(comment, this);
          var comments = this.state.data;
          var newComments = comments.concat([comment]);
          this.setState({data: newComments});
      },
      getInitialState: function() {
        return {data: []};
      },
      componentDidMount: function() {
        this.loadCommentsFromServer();
        setInterval(this.loadCommentsFromServer, this.props.pollInterval);
      },
      render: function() {
        return (
          <div>
            <div className="panel panel-info">
              <div className="panel-heading">
                <h3 className="panel-title">Put comments.</h3>
              </div>
              <div className="panel-body">
                <CommentForm onCommentSubmit={this.handleCommentSubmit} />                
               </div>
               <CommentList data={this.state.data} />         
            </div>
            
          </div>
        );
      }
    });

var Comment = React.createClass({
      render: function() {
        // var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
        return (
          <tr>
          <td>{this.props.index}</td>
          <td>{this.props.author}</td>
          <td>{this.props.comment}</td>
          </tr>         
        );
      }
    });

React.render(
  <CommentBox url="url" pollInterval={10000} />,
  document.getElementById('content')
);

また、ReactコンポートへScala.jsからアクセスするためには、アクセス用のトレイトを定義しておく必要があります。

package client

import scala.scalajs.js

trait ReactComponent extends js.Object {
  def setState(obj: js.Object): Unit = js.native
}

クライアントとサーバがやりとりするコメントのモデルクラスです。

package shared.model

case class Comment(var id: Int, var author: String, var text: String) {
   def this(author: String, text: String) {
    this(0, author, text)
  }
}

サーバとのデータ通信は、autowireを利用して実装されたシンプルなAPIを用いてjsonデータをやり取りしています。

package shared.api

import shared.model.Comment

trait CommentApi {
  def list(): Seq[Comment]
  def update(model: Comment): Seq[Comment]
  def delete(id: Int): Seq[Comment]
}


package servlets.api

import shared.model.Comment
import shared.api.CommentApi
import scala.collection.mutable.Map

object CommentApiImpl extends CommentApi {

  var idCounter = 3

  val comments = Map[Int, Comment](
    1 -> Comment(1, "Pete Hunt", "comment"),
    2 -> Comment(2, "Body Geen", "comment comment"))

  def list(): Seq[Comment] = comments.values.toSeq.sortBy { c => c.id }

  def update(c: Comment): Seq[Comment] = {
    c.id = idCounter
    comments.put(idCounter, c)
    idCounter = idCounter + 1
    list()
  }

  def delete(id: Int): Seq[Comment] = {
    comments.remove(id)
    list()
  }
}

クライアントのAjaxApiの実装です。CommentAPIへReactコンポーネントからアクセスします。

package client

import scala.scalajs.concurrent.JSExecutionContext.Implicits.runNow
import scala.scalajs.js
import scala.scalajs.js.Dynamic._
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.annotation.JSExport
import autowire._
import shared.api.CommentApi
import shared.model.Comment
import upickle.MapW
import scala.scalajs.js.annotation.JSExportAll

@JSExport
object CommentAction {

  def setComments(comp: ReactComponent, comments: Seq[Comment]) {
    if (comments.isEmpty) {
      comp.setState(js.Array())
    } else {
      val data = comments.map(t => literal("key" -> t.id, "author" -> t.author, "text" -> t.text)).toJSArray
      comp.setState(literal("data" -> data))
    }
  }
  @JSExport
  def list(comp: ReactComponent) {
    PostClient[CommentApi].list().call().onSuccess {
      case comments => setComments(comp, comments)
    }
  }

  @JSExport
  def update(c: js.Dictionary[String], comp: ReactComponent) {
    val comment = new Comment(c.getOrElse("author", ""), c.getOrElse("text", ""))
    PostClient[CommentApi].update(comment).call().onSuccess {
      case comments => setComments(comp, comments)
    }
  }

  @JSExport
  def delete(id: Int, comp: ReactComponent) = {
    PostClient[CommentApi].delete(id).call().onSuccess {
      case comments => setComments(comp, comments)
    }
  }
}

ReactコンポーネントからScala.jsで変換されたCommentAction(データ通信呼び出しとコンポーネントへの値の設定)とCommentAPIでサーバサイドとCommentオブジェクトをやり取りしています。

ReactとScala.jsを利用することにより、JqueryなどでガリガリとAjaxやDOMの操作を実装していた時に比べてずいぶんシンプルなコードで実装できていると思います。

Scala.jsやReactを用いることにより、コンポーネントベースのシングルページウェブアプリケーションが従来に比べて容易に開発できるようになってきたのではないでしょうか。

HTTP2


正式にどこかの組織に承認されたようです。

簡単にいうと対応しているサイトでは、Webの表示がすごく速くなりますよってことみたいです。

httpsがhttpより速くレスポンスが返ってくるなんて、一昔前では考えられなかったのんだけど…

このサイトでブラウザから通信速度の違いを体験できるので気になる方は試してみたください。
https://www.httpvshttps.com/

エンジニアの人はソースを頑張ってチューニングするよりは、httpsを使えるようにして新しい通信プロトコルに対応しているサーバを使ったほうが手っ取り早いでしょうね。

 

「バイアスのバランス」

Googleさんでは、無意識バイアスを取り除くために、面接時に履歴書はほぼ参考にせず、雇いたい部署で予め用意された質問を形式的に聞くらしい。
その場限りの質問が会社にとって最終的にあまり有益でないと言っているみたいです。
(バイアスとは偏りのことです)


ちなみに僕のバイアスについての考えですが、
反射的に物事に対して反応している人は、バイアスがかかりすぎてる、つまり柔軟性に乏しく、新しい情報をインプットできな人だと思われる。

だた、仕事がいつまで立っても遅いというのはバイアスがかからない人でもある。
つまり脳内で段取りが直結できてないので、いつまで立っても工夫もないしスピードもあがらない。

要はバランスの問題で、
バイアスをかけて良い事柄とかけてはいけない事柄があると思われる。
しかし、そこのバランスを見極めるのもバイアスがいるんだろう。

とバイアスがバイアスと叫んでますが…

冗談やしゃれのわからん人ほど、お笑いバイアスがかかってないんだろうねと思う。

「バイアスのバランス」が上手く効くというのは、頭がお利口なのかそうでないのかの判断になるのかもしれません。


http://gigazine.net/news/20150205-google-unconscious-bias/

生きたお金の使い方と死んだお金の使い方

生きたお金の使い方と死んだお金の使い方があるとおばあちゃんに聞いたことがある。
死んだお金の使い方をする人と飲んだことがあるが(偶発的に…)、奢られるほうはとっても残念な気分になる…

それと、奢る方は奢られる人以上に気を使わないといけないらしい。
なぜなら、奢られる方がより感謝してくれるからだそうだ。
おごってやってるんだぞと見せないほうが良い。

確かに、今までおごって頂いた人でこちらが嫌な気分にならない人は、その後も会社が大きくなってるように思う。
いつか恩を返したいと思ってしまう。
(ここがポイントなんだろうけど…)

ちなみに一番ダメなのは一切お金を使わない人なんだろう。
身の丈以上のお金は一切使う必要がないと思うのだが、なんでもケチな人には結局誰もついて行ってない。

ビジネスもプライベートもお金の使い所と使い方が非常に大事なんだと思う。

もうすぐ統一地方選挙


選挙運動費用(法定制限額)というのがあって、これ以上お金を使ったら選挙違反ですよー!という額があります。

僕の住んでる神戸市中央区は6,513,800円です。
供託金以外の額で、
ここからガソリン代やポスター代やらの税金で後で払ってくれる金額と、
事務所とかチラシやHPなど自己負担の金額が含まれます。

もちろん選挙に向けてなので、事前準備の費用なんかは自腹です。
(議員さんともなると付き合いは多いでしょう…)

神戸市の市議会議員は日本でもトップクラスで1400万超です。
ただここから税金300万ほど持っていかれるので実質は税引後が1000万円で、
保険やら年金やらで手取りは800万そこそこぐらいではないでしょうか。

選挙費用に毎年200万ぐらい貯金して、残り600万ぐらいで生活と議員のお付き合いをこなしてる感じなんですかね。
毎月の政務調査費はポスター、市政報告チラシ、視察の交通費なんかに消えちゃうし、貯金できるお金でもないし…



選挙費用を税金で支払ってくれる額は、100万そこそこぐらいかな…

結果、200万〜500万ぐらいは自腹なんでしょうね。
(どれくらいお金はかけるかにもよりますが…)

1つ忘れてましたが、市民一人あたりの議員報酬負担額は22円ぐらいだそうです。
これは、大小いろんな地域を比べて800位とかだったかな。
(ソースの記事のリンクを忘れました…)

議員報酬はトップでも、一人あたり負担額は800位。
以外に効率が良いと見るか、市政に不満ならちょっと議員の人数が少ないかもね…

4月は統一地方選挙
神戸市民の方は22円分は最低でも文句いう権利があるので、各候補者の声に少し耳を傾けてくださいませ…



http://www.city.kobe.lg.jp/information/senkyo/data/img/01-H230410_shikai_kekka.pdf