【React】componentでのonClickの使い方

ReactでonClickにメソッドをひもづけたときにundefinedエラーが出た。そのときに対応する方法がいくつかまとめておく。

問題のコード

class App extends React.Component {
  constructor() {
    super()
    this.state = { items: [] }
  }

  addItem() {
    this.setState({
      items: [...this.state.items, this.refs.name.value]
    })
  }

  render() {
    return (
      <div>
	<input ref="name" />
	<button onClick={this.addItem}>追加</button>
        <ul>{this.state.items.map((item, i) => {
          return <li key={i}>{item}</li>
	})}</ul>                                                                                                                                                                                                   
      </div>
    )
  }
}

こちらのコードを実行すると、以下のエラーが出てJavascriptでお決まり(?)のthisの問題。この場合だと、thisはbuttonになるのでsetStateなんてないよと怒られる。

Uncaught TypeError: Cannot read property 'setState' of undefined

方法1

render() {
  return (
    ・・・
    <button onClick={e => this.addItem(e)}>追加</button>
  )
}

方法2

constructor() {
  ・・・
  this.addItem = this.addItem.bind(this)
}

または

render() {
  return (
    ・・・
    <button onClick={this.addItem.bind(this)}>追加</button>
  )
}

方法3

class App extends Component {
  ・・・
  addItem = () => {
    this.setState({
      items: [...this.state.items, this.refs.name.value]
    })
  }
}

方法3は今時点ではBabel限定の書き方みたいだけど。人によって書き方違うから理解しておいた方がよさそう。個人的には方法3が1番わかりやすい。以上です。

【git】マージ済、マージ未のブランチを確認

# ブランチ確認
$ git branch
  develop
* master

# マージ済のブランチ確認
$ git branch --merged

# developブランチで作業
$ git checkout develop
〜なにか修正
$ git commit -m	"hoge"

# マージ未のブランチ確認
$ git checkout master
$ git branch --no-merged
develop

# マージ
$ git merge develop
$ git branch --merged
develop

〜 以降、developブランチに新たなコミットが加わると--no-mergedに表示される

以上です

【emacs】find-diredでファイル名検索

M-x find-dired
Run find in directory: path/to
Run find (with args): -name "hoge.php" -print

これだけなんだけど、以下みたいにやっててエラー出てた。。findコマンドで使ってるオプションそのまま投げればよいだけだったのか。。

M-x find-dired
Run find in directory: path/to
Run find (with args): "hoge.php"

# エラー
find . \( "hoge.php" \) -ls
find: hoge.php: unknown primary or operator

以上です

【angularjs】外部スクリプトの読込が完了してからコントローラを実行する

今回はGoogleMapを扱う際に気になったのでちゃんと実装してみたのでその時のメモ。htmlにscriptタグを埋め込むやり方が普通なのだろうが、そこでネットワークエラー等が発生するとhtmlを再読み込みしない限り2度と読み込むタイミングがないのではないかということを懸念してこのような形としてみた。

Router

angular.module('starter', ['ionic'])
.config(function($stateProvider) {
  $stateProvider
  .state('map', {
    url: '/map',
    controller: 'MapCtrl',
    resolve: {
      map: function(GoogleMapService) {
        return GoogleMapService.load();
      }
    }
  })
})

Service

angular.module('starter')
.service('GoogleMapService', function($q) {
  this.flag = false

  this.load = function() {
    var deferred = $q.defer()

    if (this.status) {
      deferred.resolve();
    } else {
      var self = this;
      var url = 'https://maps.googleapis.com/maps/api/js';
      var head = document.getElementsByTagName('head')[0];
      var script = document.createElement('script');

      script.src = url + '?key=APIキー';
      head.appendChild(script);

      script.onload = function() {
        self.status = true;
        deferred.resolve();
      };
      script.onerror = function() {
        deferred.reject();
      };
    }

    return deferred.promise
  }
})

さらにちゃんとやるなら、script.onerrorになったときに何度かリトライも実装した方がよいかもしれないが、今回はこんな感じで。以上です。

【JavaScript】GoogleMapで日本地図全体を中心にして全て表示

なんかのネタっぽいけどコピペ用にメモ

var div = var div = document.getElementById('map');
var map = new google.maps.Map(
  div, {
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    disableDefaultUI: true
  }
);
var latLngs = [
  [45.52289, 141.9366],
  [30.9943, 130.6605],
  [43.385351, 145.817545],
  [33.21787, 129.5525]
];
var bounds = new google.maps.LatLngBounds();
latLngs.forEach(function(latLng) {
  bounds.extend(
    new google.maps.LatLng(latLng[0], latLng[1]);
  )
});
map.fitBounds(bounds);

以上です。

「You must pass a component to the function returned by connect. Instead received」エラー対応

不慣れで相変わらず細かい事にはまってる。1つずつメモしていくしかない。コンテナとかコンポーネントとかはReactの勉強中なのでReactのそれ。ただ今回は単純にJavaScriptの使い方の問題だった。

エラーメッセージ

You must pass a component to the function returned by connect. Instead received undefined.
問題のコード

コンテナ(呼ぶ側)

・・・
import { user } from './components/user' // ★ここでエラーになってる
・・・

コンポーネント(呼ばれる側)

import React from 'redux'
class User extends React.Component {
  render() {
    return (
      <div />
    )
  }
}
export default User
解決作

コンテナ(呼ぶ側)

・・・
import user from './components/user' // 中括弧とる
・・・

以上です