あんまり知られてなさそうだけど個人的に便利なのでは?っておもってるnode modules紹介

あんまり知られてなさそうだけど個人的に便利なのでは?っておもってるnode modules紹介

はじめに

この記事は,SLP KBIT Advent Calendar 2017 の6日目の記事です.

maybe-baby

NPM

maybe-bebyMaybe monadをjavascript上に実装したものです. (公式READMEより)

これは,いわいる nullable な変数を安全に扱うためのライブラリです.
類似するライブラリとしては, lodash.get などが上がります
Reactなどの開発などで,レスポンスを受け取るまでは,propsの一部nullで,nullの間だけぐるぐる回すという処理はよく書くことがあると思います.
そういったときに,これを使うと結構便利です.

結構いろんな関数が生えているのですが,Reactで開発する上で僕がよく使う方法を紹介します.

たとえば,初期状態がnullでサーバーからtodoListを取得してそれを流し込んでる場合とします.
そして,nullのときは,<PreLoader /> そうじゃないのは,一覧を表示するケースのとき
こんな感じでかけます.

import React from 'react';
import M from 'maybe-baby';

class TodoListComponent extends React.Component {
  get maybeTodoList() {
    return M.of(this.props).props("todoList");
  }

  render() {
    if (this.maybeTodoList.isNothing()) return <Preloader />;
    reutrn (
        <ul>
          {
            this.maybeTodoList.join().map(todo => (
              <li>{todo.content}</li>
            ))
          }
        </ul>
    );
  }
}

結構わかりやすいし,こういったライブラリで null チェックの記法を統一できて,いーかんじ.
join() した後にmapすると,maybeObj の持っている map なのか, Array.prototype.map なのかが
わかりづらいのが時々つらい.

babel-plugin-pipe-composition

ビット演算子(<<)と(>>)をオーバーロードして、F#のようなパイプの前方/後方の振る舞いを提供する (READMEより)

NPM

これは,tc39/proposal-pipeline-operator のようなパイプラインオペレーターをbabel-pluginを使って実装したものです.

|> ではなく >> の理由は,babelが内部的に使っているparserであるbabylonでパースできないからだと思います.

これは,プロダクションのコードに導入するのはちょっと色々 だいぶ冒険してるな? という感じがありますが,趣味プロジェクトで ES7のプロポーサルな記法を先取り的に使うにはいいと思います.

僕,このパイプライン演算子が結構好きなんですよね,(日本語的な表現に近いと思っている)

this.dispatch(trySignIn(this.state.user))

上のようなコードを次のようにかけて,

this.state.user >> trySignIn >> this.dispatch

これって,現在の状態のユーザー情報を使ってサインインを試みてその結果を通知する.
みたいに,A をつかって B して C して D する っていう表現に向いているとおもうんですね.

早く,javascriptの記法として,せめて babel の stage に乗ってほしいなーとめっちゃ思います.

Ramda

NPM

このモジュールをマイナーというのは,だいぶナンセンスだとは思いますが,一部の人しかしっていないイメージがあるので.

位置的には,lodashなどの関数を集合させたライブラリに位置すると思います.
lodashとは少しゴールが違い,より関数型プログラミングに寄せたモジュールだと思います.

大きな特徴としては,提供している関数すべてがカリー化されており,部分適合が可能という点です.
あと,パイプライン演算子とめちゃくちゃ相性が良いです.

例えば,ramda.js と 組み合わせると
n人の5教科のテストの点数から,平均を求めて,平均点が50点以上の人の数を数えるという
ロジックを問題文を読み解くように書くことができます.

[[10, 30, 70, 80, 50], [90, 50, 55, 70, 60], [50, 40, 20, 30, 10]]
  >> R.map((v) =>
       v
         >> R.sum
         >> v => v / 5
     )
  >> R.filter(v => v >= 50)
  >> R.length

これは完全に主観ですが,コードも読みやすくなっていると思います.


アドベントカレンダーの投稿時間が過ぎた後の追記 :bow:

auto-bind

NPM

jsのクラス記法を使って,イベントリスナにインスタンス関数を登録するとき,this の scopeが変わってしまうという問題があります.

それを解決するのに,一般的に .bind(this) するという習慣があると思います.

ただ,毎回それを書くのは冗長だと思います.
そういったときにこのモジュールの出番だと思います.


class Sample {
  constructor() {
    EE.addListener('any-aciton1', this.doSomeThing1.bind(this))
    EE.addListener('any-aciton2', this.doSomeThing2.bind(this))  
  }
  // ・・・
}

とするところを,

import autoBind from 'auto-bind'

class Sample {
  constructor() {
    autoBind(this)
    EE.addListener('any-aciton1', this.doSomeThing1)
    EE.addListener('any-aciton2', this.doSomeThing2)
  }
  // ...
}

のように書くことができ,冗長な箇所を省くことができます.
類似したもので,react用のものもあります.

NPM

これは,Reactのライフサイクルメソッドを除いたそれ以外の関数を .bind(this) してくれるやつです.
auto-bind から ライフサイクルを ignoreしただけですね.

こんな感じで使えます.

import autoBind from 'react-autobind'
import React, { Component } from 'react'

class Sample extends Component {
  constructor(props) {
    super(props)
    this.state = {}
    autoBind(this)
  }

  handleClick(e) {
    // do some thing
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>submit</button>
      </div>
    )
  }
}

hover や blur で event の量が多くなるときは, auto-bind 指定おいてもいいかもしれませんね.
.bind(this) し忘れも防げて良いでしょう.

さいごに

いかがでしょうか.
趣味プロジェクトで使っていて気持ちがいいものを中心に紹介をしてみました.
もっとたくさんのモジュールを紹介したかったのですが,投稿時間が迫ってきたので
このあたりで締めくくりたいと思います.