Reactのhooksで最初の一回目をスキップするCustom Hooksを作る


一回目をスキップするCustom Hooks

はじめに

そろそろReactでhooksが使えるようになって一年が経ちます。主要なライブラリなどはClassコンポーネントからhooksを利用したFunctionalコンポーネントに置き換わっています。
弊社hokanでもhooksを積極的に採用しています。
さてそんな中、ClassコンポーネントにはあったcomponentDidUpdateに該当するhooksはないという壁にぶつかりました。
初回は何もしないが2回目以降はなにか処理をはさみたいなどがユースケースにあると思います。そんな便利なCustom Hooksを作成したので紹介します。

実装

import {DependencyList, useEffect, useState} from 'react';

export default function useSkip(effect: Function, deps: DependencyList, times: number = 1) {
  const [_times, setTimes] = useState(0);
  useEffect(() => {
    if (_times >= times) {
      return effect();
    } else {
      setTimes(_times + 1);
    }
  }, deps);
}

解説

hooks名はuseSkipとしました。

引数

基本的な使い方は、useEffectと変わりません。第一引数にコールバック関数、第二引数にDependencyListを渡します。
第三引数で何回処理を飛ばすかを渡すことができます。多くの場合、1回しかとばす需要がなさそうなのでデフォルトでtimes=1としておきます。

実行回数の管理

  const [_times, setTimes] = useState(0);

この部分で実行回数を管理する状態を保持します。

    if (_times >= times) {
      return effect();
    } else {
      setTimes(_times + 1);
    }

この部分で引数の回数に到達していない場合は、コールバックを発火させず、実行回数をインクリメントします。
指定の回数に到達した時点でコールバックが発火し始めます。

動作確認

以下のプログラムで動作を確認します。
ボタンを押したときのuseEffectuseSkipで渡しているコールバックが発火するかを観察します。



import React, {useEffect, useState} from 'react';
import useSkip from '@hooks/useSkip';

function App() {
  const [num, setNum] = useState(0);

  useEffect(() => {
    console.debug(`num: ${num}`);
    console.debug('fire useEffect');
  }, [num]);

  useSkip(() => {
    console.debug('fire useSkip');
  }, [num]);

  useSkip(
    () => {
      console.debug('fire useSkip 5 times skipped');
    },
    [num],
    5
  );

  return <button onClick={() => setNum(num + 1)}>increment</button>;
}


初回はuseEffectのみですが、2回目から1つ目のuseSkip、5回目からは2つ目のuseSkipが発火しています。
いい感じですね。componentDidMountに等しい処理もできそうです。

参考