初めに
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パフォーマンスを学んでいく中で多くの学びがありました。今後も勉強・実践して力をつけていきます。