関数を返す関数の活用
2022/05/19
まずとあるコード(React)をお見せします。
sample.tsx
import React, { useState } from 'react'
const Sample: React.FC = () => {
const [player, setPlayer] = useState('')
const onClick1 = () => {
setPlayer('John')
}
const onClick2 = () => {
setPlayer('Sam')
}
const onClick3 = () => {
setPlayer('Mike')
}
return (
<div>
<h2>Player: {player}</h2>
<button onClick={onClick1}>John</button>
<button onClick={onClick2}>Sam</button>
<button onClick={onClick3}>Mike</button>
</div>
)
}
export default Sample
どのような感想を持ちましたか?
個人的にはonClick
まわりが冗長に感じます。
これはDRYの原則から見ても綺麗なコードとは言い難いです。
このようなコードはReactに限らず様々な言語、フレームワークでプログラミング初心者にありがちな実装です。
では綺麗にまとめるにはどのようにすればよいでしょうか? そこで利用できるのが関数を返す関数(高階関数)です。
高階関数とは
高階関数とは
- 関数を引数に取る
もしくは
- 関数を返す
関数のことです。
関数を引数に取る関数はJSにおけるmap
やreduce
のようなものですが、
関数を返す関数は以下のようなものになります。
const compareFactory = (threshold: number) => (value: number) => {
if (value > threshold) {
console.log(`${value} is more than ${threshold}`)
} else if (value === threshold) {
console.log(`${value} is equal to ${threshold}`)
} else {
console.log(`${value} is less than ${threshold}`)
}
}
const compare1 = compareFactory(1);
const compare2 = compareFactory(2);
compare1(2) // 2 is more than 1
compare1(1) // 1 is equal to 1
compare2(2) // 2 is equal to 2
compare2(1) // 1 is less than 2
ぱっと見どのような場面で使えるか分かりづらいですが、この関数を返す関数を利用することで、最初のコードを簡潔にすることができます。
高階関数を利用すると...
高階関数を利用すると最初のコードは以下のように書けます。
sample.tsx
import React, { useState } from 'react'
const Sample: React.FC = () => {
const [player, setPlayer] = useState('')
// 高階関数
const onClick = (name: string) => () => {
setPlayer(name)
}
return (
<div>
<h2>Player: {player}</h2>
<button onClick={onClick('John')}>John</button>
<button onClick={onClick('Sam')}>Sam</button>
<button onClick={onClick('Mike')}>Mike</button>
</div>
)
}
export default Sample
無駄にonClick
関数を定義する必要がなくなったので、シンプルにまとまりました。
同じような定義がされている関数は高階関数でまとめられることが結構多いです。 似たような関数が複数あれば、「あれ?これ高階関数でまとめられないかな?」と考えてみるといいかもしれません。