1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

HCB Advent Calendar 2021Advent Calendar 2021

Day 23

リファクタリングチャレンジ Web Speed Hackathon 2021 mini

Last updated at Posted at 2021-12-26

初めに

HCB Advent Calendar 2021
アドベントカレンダー23日目の記事になります。(大遅刻:26日)

テストコードやパフォーマンスチューニングができないWebフロントエンジニアの需要は少ないといわれたので、
必死こいて勉強する記事です。今回は、コードを読んで、処理に無駄がありそうなところや、操作性が悪くなっているところを発見し、修正する回にしようと思います。(スコアは見ません。)

ゆるく記事を書くので興味がある方は覗いてってください(メモ書きのような記事です)

勉強資料として
Web Speed Hackathon 2021 mini
を使います。

本題

条件分岐

./client/src/components/application/Navigation/Navigation.jsx
無駄な条件分岐があったので統一

{activeUser !== null ? (
  <NavigationItem
    icon={<FontAwesomeIcon iconType="edit" styleType="solid" />}
    onClick={onRequestOpenPostModal}
    text="投稿する"
    />
) : null}
{activeUser !== null ? (
  <NavigationItem
     href={`/users/${activeUser.username}`}
     icon={<FontAwesomeIcon iconType="user" styleType="solid" />}
     text="マイページ"
     />
) : null}
{activeUser === null ? (
  <NavigationItem
    icon={<FontAwesomeIcon iconType="sign-in-alt" styleType="solid" />}
    onClick={onRequestOpenAuthModal}
    text="サインイン"
    />
) : null}      

{activeUser !== null ?
  (
    <>
      <NavigationItem
        icon={<FontAwesomeIcon iconType="edit" styleType="solid" />}
        onClick={onRequestOpenPostModal}
        text="投稿する"
        />
      <NavigationItem
        href={`/users/${activeUser.username}`}
        icon={<FontAwesomeIcon iconType="user" styleType="solid" />}
        text="マイページ"
        />
      </>
  )
  :
  <NavigationItem
  icon={<FontAwesomeIcon iconType="sign-in-alt" styleType="solid" />}
  onClick={onRequestOpenAuthModal}
  text="サインイン"
  />
}

addEventListenerのpassiveオプション

addEventListenerのpassive設定をtrueにしてあげると、preventDefaultを読んでいないことをブラウザに伝達する。preventDefaultをしないと、eventListenerを実行するたびに、毎回設定された関数を再解釈し、すべて実行してしまう。そうなると、処理として記述されている2の18乗回の処理がスクロールするたびに実行されて、とても操作できない動作になる。(そもそも2の18乗とか絶対いらない...)

    const handler = () => {
      // 念の為 2の18乗 回、最下部かどうかを確認する
      const hasReached = Array.from(Array(2 ** 18), () => {
        return window.innerHeight + Math.ceil(window.scrollY) >= document.body.offsetHeight;
      }).every(Boolean);

      // 画面最下部にスクロールしたタイミングで、登録したハンドラを呼び出す
      if (hasReached && !prevReachedRef.current) {
        // アイテムがないときは追加で読み込まない
        if (latestItem !== undefined) {
          fetchMore();
        }
      }

      prevReachedRef.current = hasReached;
    };

    // 最初は実行されないので手動で呼び出す
    prevReachedRef.current = false;
    handler();

    document.addEventListener('wheel', handler, { passive: false });
    document.addEventListener('touchmove', handler, { passive: false });
    document.addEventListener('resize', handler, { passive: false });
    document.addEventListener('scroll', handler, { passive: false });
    return () => {
      document.removeEventListener('wheel', handler);
      document.removeEventListener('touchmove', handler);
      document.removeEventListener('resize', handler);
      document.removeEventListener('scroll', handler);
    };

promise処理のつなげ方

promiseはメソッドチェーンを使って処理に成功した時と、失敗した時の処理をまとめてかける。

const promise = fetcher(apiPath);

promise.then((allData) => {
  setResult((cur) => ({
    ...cur,
    data: [...cur.data, ...allData.slice(offset, offset + LIMIT)],
    isLoading: false,
  }));
  internalRef.current = {
    isLoading: false,
    offset: offset + LIMIT,
  };
});

promise.catch((error) => {
  setResult((cur) => ({
    ...cur,
    error,
    isLoading: false,
  }));
  internalRef.current = {
    isLoading: false,
    offset,
  };
});

fetcher(apiPath)
  .then((allData) => {
    setResult((cur) => ({
      ...cur,
      data: [...cur.data, ...allData.slice(offset, offset + LIMIT)],
      isLoading: false,
    }));
    internalRef.current = {
      isLoading: false,
      offset: offset + LIMIT,
    };
  })
  .catch((error) => {
    setResult((cur) => ({
      ...cur,
      error,
      isLoading: false,
    }));
    internalRef.current = {
      isLoading: false,
      offset,
    };
  });

最後に

今回まともに記事を書いてないうえに、大遅刻していますがここまでにしたいと思います。
Webパフォーマンスを学んでいく中で多くの学びがありました。今後も勉強・実践して力をつけていきます。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?