なるほどの〜
丸括弧が2つある構造を文法的に理解できていない
ゆうことやと、まず以下のコードで話しよか〜。下のコードでconst plusFunction
に入れてるもんは、どないなことになっとるか、説明できるかのう?
javascript
1const plusFunction = (a) => {
2 const func = (x) => x + a;
3 return func;
4}
plusFunction
は引数a
を受け取る関数やねんな。で、何を返す関数かゆうと、関数を返してるんやな。どういう関数かゆうたら、(x) => x + a
ゆう関数やね。つまりx
を受け取って、そのx
に a
を足して返しとるわけやんか。そやから、
javascript
1const addTen = plusFunction(10);
とすると、与えられた引数に10を足した結果を返す関数をplusFunction(10)
が返してきて、それを変数 addTen
に入れたわけや。そやから
javascript
1const y = addTen(5);
とすると y
には 15 が入ってくるわけやな。
javascript
1console.log(y); // => 15
ほなら、plusFunction
に別の数を与えてみよか〜
javascript
1const addThousand = plusFunction(1000);
こうすると、addThousand
には、与えられた引数に1000を加えた結果を返す関数が入ってくるねんな。そやから addThousand
に 111 を渡せば、1111 が返されるねんな。
javascript
1const z = addThousand(111);
2
3console.log(z); // => 1111
➡ サンプル
ほんで、ここまでの話が、k49977はんにとって、「そんなんJavaScriptの基本のキや。知っとるがな!」ゆう話なのか、「なんやソレ。そないなplusFunctionみたいなもん、書けるん知らんかったわ〜」ゆう話なのか、そこがひとつポイントですわ。
知らんかったなら、
connectでググったりしてみた
そうやけど、ググるべき用語は、まずは「第一級関数」やもしれへんね。要は、関数もオブジェクトなので、関数を返す関数だったり、関数を引数に取る関数とかを、フツーにシレっと書けるゆうことやねん。ほんで話もどすと、上の例のplusFunction
は、関数を返す関数になっとるわけや。こういうの**高階関数(higher-order function)**いいますう。
で、こういうplusFunction
作ると、10を加える関数作ってaddTen
だったり、1000を加える関数作ってaddThousand
だったりの変数に入れることができるのやけど、addTen
を何回も使うわけではないのなら、わざわざaddTen
ゆう中間の変数に入れへんでも
javascript
1const addTen = plusFunction(10);
2
3const y = addTen(5);
となっているのを、addTen
を無くして詰めて、
javascript
1const y = plusFunction(10)(5);
と書いてもええねんな。これエラーにならずちゃんと動くで。➡サンプル
ほんで、上のコードのplusFunction(10)(5)
やけど、(10)(5)
ゆうことで丸カッコ連続しとるわな。で、ここで質問の本題につながるんやけど、react-reduxのconnect
使うとき丸カッコが2つ連続するのも、上のplusFunction
の後ろに丸カッコ2回連続で書けるのと同じ理屈や。connect
も、1個目の丸カッコまでんとこ
javascript
1connect(
2 mapStateToProps,
3 mapDispatchToProps
4)
で関数が返ってくるねん。どういう関数かゆうたら、Reactコンポーネントを引数として受け取って、そのコンポーネントとRedux storeとをコネクトつまり接続する的な処理をしたReactコンポーネントを返してくれるねん。コンポーネントを引数として受け取り、何がしかのことをやって元のコンポーネントに機能を付加したコンポーネントを返す関数を 高階 (Higher-Order) コンポーネント略してHOC いいますう。そやから、connectは、mapStateToPropsやmapDispatchToPropsだったりを受け取って、HOCを返してくれる関数ですねん。react-redux のドキュメントでconnectが何を返すかの説明んとこ のサンプルコードの中にも
javascript
1// first call: returns a hoc that you can use to wrap any component
2const connectUser = connect(mapState, mapDispatch)
という二行があるわな。コメントよう見ると、 first call: returns a hoc ...
ってありまっしゃろ?これの中のhoc
ゆうんは、さっき言うた、高階 (Higher-Order) コンポーネントのことですねん。まあ、仕事の現場では、みんな「ホック」ゆうてますわ。公式のそこんとこのサンプルコードの上のほうのやつ:
javascript
1import { login, logout } from './actionCreators'
2
3const mapState = (state) => state.user
4const mapDispatch = { login, logout }
5
6// first call: returns a hoc that you can use to wrap any component
7const connectUser = connect(mapState, mapDispatch)
8
9// second call: returns the wrapper component with mergedProps
10// you may use the hoc to enable different components to get the same behavior
11const ConnectedUserLogin = connectUser(Login)
12const ConnectedUserProfile = connectUser(Profile)
を、
In most cases, the wrapper function will be called right away, without being saved in a temporary variable:
とあるように、中間の変数(temporary variable)を省いて書けば下の
javascript
1import { login, logout } from './actionCreators'
2
3const mapState = (state) => state.user
4const mapDispatch = { login, logout }
5
6// call connect to generate the wrapper function, and immediately call
7// the wrapper function to generate the final wrapper component.
8
9export default connect(mapState, mapDispatch)(Login)
という、丸カッコが2つ連続するやつになるわけねんな。
繰り返すけど、これは冒頭に挙げたplusFunction
のサンプル
javascript
1const addTen = plusFunction(10);
2
3const y = addTen(5);
を、addTen
省けば
javascript
1const y = plusFunction(10)(5);
と、丸カッコ2個続けて書くのと同じことやねん。そして、plusFunction(10)(5)
と書ける理屈としては、JavaScriptの関数が第一級だからゆう話になるわけや。
わかってもらえたかの〜
話だけだとしっくりこないんやったら、plusFunction
みたいな関数を返す関数や、HOCの簡単なサンプル、そして(connect同様に)HOCを返す関数のサンプルを自分で書いてみるといいかもしれんね。
ほな、また〜
追記:
ちょっと混乱させてしまうかもやけど、f
が、関数を返す関数であるとすると、f
が返す関数を実行するところまでを一度に書くと、上で説明したとおり、f(・・・)(・・・)
と丸カッコが2連続になるわけやけど、もう一段増やして、f
が、関数を返す関数を返す関数であるとすると、すべての段階の関数を実行するには、f(・・・)(・・・)(・・・)
と丸カッコを3連続で書くことになります。さらにもう一段階増やして、f
が、関数を返す関数を返す関数を返す関数、であるとすると、f(・・・)(・・・)(・・・)(・・・)
とカッコを4つ連続で書くことになる。以下同文や。
たとえば、4つ連続でカッコを書くことになるf
の例 ➡ サンプル