LoginSignup
2
2

More than 3 years have passed since last update.

ファーストビューの効率化のために、ファーストビューのタイミングで不要なものを遅延ロードにしていたのですが、reducerを遅延させるのもいいかなと思えてきました。

reducerが必要となるタイミング

コンポーネントを描画した直後にdispatchを行う必要性というのは、そうそう生じないものです。ユーザーインタラクションでしかdispatchが行われない、ということでしたら、コンポーネントを作成したタイミングで遅延ロードを開始して、そこから1秒もしないうちにロードされる、というようなタイミングでじゅうぶん間に合います。

そして、巨大なオブジェクトを取り扱うreducerは、往々にして多くのコードを必要とします。

とはいえ、ふつうのReact.useReducerでは、reducer関数は同期的に必要となってしまいます。

useLazyReducerを作ってみた

ということで、遅延ロードでreducerをロードするようなHooksを立ててみました。

// ロード前は何もしないreducerを入れておく
const temporaryReducer = (store, _action) => store;

export default function useLazyReducer(lazyReducer, initialArg, initializer) {
  // 遅延データを入れる
  const reducerRef = React.useRef(temporaryReducer);

  React.useEffect(() => {
    lazyReducer().then((obj) => {
      reducerRef.current = obj.default;
    });
  }, [lazyReducer]);

  const reducer = React.useCallback(
    (store, action) => reducerRef.current(store, action),
    []
  );

  return React.useReducer(reducer, initialArg, initializer);
}

仕掛けとしてはごく単純で、reducerとしてセットする関数はrefの中身につなぐだけ、としておいて、遅延ロードでrefを書き換える、というものです。lazyReducerとして渡すものは、React.lazyに倣って、「{default: reducer関数}resolveするPromiseを返す関数」を受け取るようにしてあります。

使用感

遅延ロードが間に合わないぐらいのタイミングでユーザー操作に入るのは現実的に困難ですので、これで十分に間に合っている印象です。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2