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

メンチカツ

ロースカツが好きです

【メモ】dockerに「Error response from daemon: client is newer than server」と言われる

docker氏に、クライアントとサーバーのAPIバージョンが相違しているよ!って怒られた

$ docker version

Client:
 Version:      1.12.0
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 21:15:28 2016
 OS/Arch:      darwin/amd64
Error response from daemon: client is newer than server (client API version: 1.24, server API version: 1.23)

ggると docker-machine upgrade default すれば治るよ!とあるけど、改善されない、そんなときは 環境変数 DOCKER_API_VERSION を設定します。

export $DOCKER_API_VERSION=1.23

設定後、再度 docker-machine upgrade default すると、無事にバージョンを

docker version
Client:
 Version:      1.12.0
 API version:  1.23
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 21:15:28 2016
 OS/Arch:      darwin/amd64

Server:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 17:52:38 2016
 OS/Arch:      linux/amd64

合わせられてないやんけ。 でもサーバーのAPIバージョンがあげられたぞ???

そこで、環境変数 DOCKER_API_VERSION を更新してみます。

export $DOCKER_API_VERSION=1.24

その後dockerをrestartすると、やっとバージョンが合いました。

Client:
 Version:      1.12.0
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 21:15:28 2016
 OS/Arch:      darwin/amd64

Server:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 17:52:38 2016
 OS/Arch:      linux/amd64

コミットハッシュに変更がないので、どうやら見た目が変わっただけなんですけどね。 ひとまず状況は解決できました。

ggったページ

github.com

【メモ】MyBatisのMapperでオーバーロードをしてはいけない

MyBatisで

public interface UserMapper {

  @Select("SELECT * FROM users")
  List<User> getUsers();

  @Select("SELECT * FROM users WHERE category_id = #{categoryId}")
  List<User> getUsers(@Param("categoryId") Integer categoryId);

}

と定義してビルドする。

と、以下のように怒られる😇

java.lang.IllegalArgumentException: Mapped Statements collection already contains value for jp.co.hoge.core.mapper.UserMapper.getUsers

これは、interface内でメソッド名を一意にすると解決します😙

public interface UserMapper {

  @Select("SELECT * FROM users")
  List<User> getUsers();

  @Select("SELECT * FROM users WHERE category_id = #{categoryId}")
  List<User> getUsersByCategoryId(@Param("categoryId") Integer categoryId);

}

【メモ】webpack.optimize.UglifyJsPluginでbuildしてもコメントが残っちゃうんだよねってとき

Reactアプリでリリースってなったとき、みんなやりたいのがjsファイルのminify。

webpackのドキュメント

list of plugins

に習い、webpack.config.jsで

plugins: [
  new webpack.optimize.UglifyJsPlugin({
    compress: {
        warnings: false
    }
  })
]

を追加するも、ビルドしたソースにはコメントやスペースがもりもり残ってる。。😇

そんなときはjsのloaderにoptionを追加。

module: {
    loaders: [
        {
            test: /\.js$/,
            loader: 'babel',
            query: {
                comments: false,
                compact: true
            },
            exclude: /node_modules/,
            include: __dirname
        }
    ]
}

babel-loaderのqueryに追加できるoption

babeljs.io

無事、いい感じにminifyできました。

【メモ】React,Reduxのリファクタリングはじめの一歩

よくわからないままはじめ、まさに習うより慣れよで身につけつつある Reduxスキル。 最初のほうに作ったソースを見直すと、ある共通点に気がつきました。

無駄なstateが多い!

propsで受け取った値をわざわざコピーしてstateで保持してたりします。 変更される値はイベントハンドラの引数で受け取れるので、捕捉した値を propsのイベントで上位のコンポーネントに伝搬してしまえば、stateを 用意する必要がある箇所をぐっと減らすことができました。

//before:こういうかんじの記述が多かった
handleChange(e) {
    const textValue = e.target.value
    this.setState({
        textValue: textValue
    }, this.props.onChange(textValue))
}

//after:丸投げでスッキリ
handleChange(e) {
    this.props.onChange(e.target.value)
}

変更フォームなど、propsで変更前、stateで変更後の値を保持して 比較したり、リセットボタンを押したら変更前の値に戻すとか、そういう 時以外はstateは最小限がソースが見やすいな、と思いました。

Reactで「Uncaught TypeError: Cannot read property 'props' of null」が出る

render(){
  return <myCompornent onClick={this.handleClick}></myCompornent>
}

ってやって、myCompornent側で

onClick(){
  this.props.onClick()
}

とかやると

Uncaught TypeError: Cannot read property 'props' of null

とエラーしてしまいます。

これは、

<myCompornent onClick={this.handleClick.bind(this)}></myCompornent>

とすることで回避できます。

これはes6の仕様です。es5で書かれたReactチュートリアルを写経すると発生しがちです。

qiita.com

きっちり写経したのにエラーしてしまう。。typoしてんのかな??

とか陥りがちなポイントです(というか陥った)。

React + React Bootstrap で、htmlでお知らせが書けるツールチップを使いたい

こういうやつが欲しい。

f:id:easy-breezy:20160608154337p:plain

そこで

<Info message={message} />

こういうコンポーネントを作成したところ、messageに与えた文字列のhtmlタグがエスケープされて、そのまま出力されてしまう。

<Info message="Hello,<br/><br/><strong>world!!!!!!</strong>" />

// => Tooltipに「Hello,<br/><br/><strong>world!!!!!!</strong>」

それで、同じ壁にぶち当たってる人を探したら、いた。

stackoverflow.com

なるほどArrayで渡せば良いらしい。

<Info message={[
    "Hello,", <br/>, <br/>,
    <strong>world!!!!!!</strong>, <br/>
]}/>

これをInfoコンポーネントの中で this.props.message.join() すればよいのか、と思いきや、

Warning: Each child in an array or iterator should have a unique "key" prop.

キーつけなさいよ!っておこられる。上のリンク先にもそうレスがありますね。

というわけでキーをつけます。

getMessage() {
        return this.props.message.map(function (m, index) {
            return <span key={index}>{m}</span>
        })
}

できあがったものはこちら。

import React, { PropTypes, Component } from 'react'
import { Tooltip, OverlayTrigger } from 'react-bootstrap'
import SHA256 from 'crypto-js/sha256'

class Info extends Component {

    static propTypes = {
        message: PropTypes.array.isRequired,
        placement: PropTypes.string
    }

    getMessage() {
        return this.props.message.map(function (row, index) {
            return <span key={index}>{row}</span>
        })
    }

    render() {
        const message = this.getMessage()
        const tooltip = <Tooltip id={SHA256(new Date()).toString()}>{message}</Tooltip>
        return (
            <span className="info">
                <OverlayTrigger placement={this.props.placement} overlay={tooltip}>
                    <i className="fa fa-info-circle"></i>
                </OverlayTrigger>
            </span>
        )
    }
}

export default Info

2016/08/10追記

パラメータのところ

<Info message={[
    "Hello,", <br/>, <br/>,
    <strong>world!!!!!!</strong>, <br/>
]}/>

は、要はjsxの書式ならOKなので、

<Info message={[<span>Hello,<br/><br/><strong>world!!!!!!</strong><br/></span>]}/>

こっちのほうがスッキリしますね。

ESLintに「"$" is not defined no-undef」と怒られた

componentDidMount() {
    $.get('/data/hoge.json', function (result) {
        this.setState({
            hogeList: result
        });
    }.bind(this));
}

上記を定義したReactコンポーネントをESLintでテストすると怒られた。

error  "$" is not defined           no-undef

これは .eslintrcのenvにjqueryを追加することで解消する。

{
  "env": {
    "jquery": true
  }
}

参考にしたページ github.com