カスタムフックの戻り値は配列かオブジェクトか

結論

どっちでもいい。 が、以下の方針に従うのがいいような気がします。

  • 返却される値を全て利用する場合が多い→配列
  • 返却される値の一部を利用する場合が多い→オブジェクト

例えばReact標準フックのuseStateを考えてみます。
useStateは値とその更新関数をセットで利用するケースが多い・かつ複数利用するシーンに備えてそれぞれ別の変数名にすることを想定していると考えると、配列で返却することで利用側が柔軟に使用できるようにしているように思います。 以下のような感じですね。

const [count, setCount] = useState(0);
const [input, setInput] = useState("");

とまぁこれだけでは寂しい気もするので、それぞれのメリットデメリットについてもう少し見ていきたいと思います。

呼び出し側から見た場合のメリット・デメリット

タイプ メリット デメリット
配列 任意の名前をつけられる 利用しない変数も宣言する必要がある
オブジェクト 利用する値のみの宣言ができる 名前を変更する場合多少手間

メリットとデメリットを詳しく

上記で表にまとめたメリット・デメリットを実際のコードで確認していきます。  

// 配列を返すカスタムフック
export function useFunction1() {
    
    return [count, func]
}

// オブジェクトを返すカスタムフック
export function useFunction2() {
    
    return { count, func }
}

変数名の付け方

// 別名をつけられる
const [myCount, myFunc] = useFunction1();
// そのままの名前(キー名)を使用する必要がある
const { count, func } = useFunction2();

ただ、オブジェクトの場合も分割代入を利用すると別名を付けられます。

const { count: myCount, func: myFunc } = useFunction2();
console.log(myCount);

利用したい変数のみの宣言

// 配列の場合は各値をそれぞれ宣言する必要がある。使用しない場合は下記のように`,`や``_`を利用する。
const [ , myFunc] = useFunction1();
// オブジェクトの場合は利用したい値のみを宣言すればよい。
const { func } = useFunction2();

配列の場合はarr[1]のみ利用したい場合にarr[0]を宣言する必要があるので_や上記のような空白カンマで利用しないことを明示する必要があります。  

まとめ

現時点での私の考えははじめにで述べた通りです。が、そこまで厳格なルールがあるわけでもないので適宜決めていけばいいのかなと思います。