toshi-toma blog

主にフロントエンド、作業ログあとは色々なメモ ✍️ 🍅

2023年の振り返り

今年も1年を振り返っていきます。

お宮参りで行った神社から見える風景

去年の振り返り

toshi-toma.hatenablog.com

TL;DR

  • 子供が産まれて育休を取得した
  • 5月に転職して医療系のスタートアップで働いてる

子供が産まれた

今年1番大きかったのは7月に子供が生まれたことです。7月から10月に3ヶ月間の育休を取得して、育児に奮闘していました。

想定していたより大変だったので、育休を取得して本当に良かったです。あとは日々子供が成長していくので、それをしっかり見ておけるというのが大きいです。すでに新生児期のサイズ感とかも思い出せないので、毎日が貴重だなと思います。

落ち着いてきたかなと思ったら夜泣きが始まったりと、常に新しい課題が出てきてバタバタですが、これまでの人生とはまた違った幸福感があります。

どんどん可愛さを更新していってビビります。

仕事

去年はフロントにReact Nativeがメインでしたが、年明けから4月ごろまでは久しぶりにがっつりWebの開発を担当していました。やはりWebの開発体験が好きです。

そして4月から1ヶ月ほど有休消化をして、5月に株式会社Linc'well に転職しました。

子供が産まれるタイミングで転職をしたので悩みや不安が多かったですが、今振り返ると、大きな問題もなく今の仕事を楽しめてるので良かったなと思います。

note.com

相変わらず愛媛からフルリモートで働いてますが、今の職場は定期的にオフラインで集まる機会があり何度か東京に出張で行ったりしました。やはりみんなでオフラインで集まることの意義を感じます。

初めて医療ドメインで働いていますが、取り扱う課題が自分ごと化しやすかったり、必要な知識も興味を持って学べてるので、楽しく働けています。

複業

去年から継続してたフロントエンドの開発案件を4月ごろまで続けてました。

転職や子供が産まれることもあり、副業は一旦ストップしました。

来年は厳しいかもしれないけど、もう少し落ち着いたら再開したいなと思います。

開発、学習

本業で使うこともあり、RubyRailsAWS周りについてキャッチアップしました。これまでずっと静的型付け言語だったこともあり、若干苦戦してますが、ChatGPTやCopilotがあるので、今は新しい技術を学ぶのがやりやすいなーと思います。

あとは抱っこの時間が長いので、カンファレンスの動画見たりして過ごしました。

今年読んだ技術書

  • フロントエンド開発のためのセキュリティ入門
  • フロントエンド開発のためのテスト入門
  • Good Code, Bad Code ~持続可能な開発のためのソフトウェアエンジニア的思考

toshi-toma.hatenablog.com

プライベート

プライベート面は出産・育児と初めてのことで一杯一杯な日々でした。 1日がよりあっという間になり、今年はこれまで以上に短く感じました。

音楽系だと去年に続き、BE:FIRSTをずっと見たり聴いたりしてます。あとはK-POPにハマり気味で、IVEやNewJeansをよく聞いていました。

あとは子供が産まれる前や、なんだかんだ抱っこしてる時間にNetflixなどでコンテンツを消化してました。

  • コンテンツ

    • ポケモンSV
      • 久しぶりにちゃんとゲームやった。子供の時にやってたポケモンと違いすぎ
    • ドラマ コウノトリ
      • 子供が産まれる前に見てた。めちゃ感動するしいい話
    • ハンターハンター
      • アニメだけどついに見た!
    • キングダム
      • アニメだけどついに見た!
    • The Voice Japan
      • Amazon Primeでみた歌のオーディション。ハマった。
    • ラブトランジット
      • Amazon Primeでみた。バチェラーより面白かった。
    • Netflix サンクチュアリ
    • Netflix 御手洗家、炎上する
    • Netflix ウヨンウ弁護士は天才肌
      • 今年見たもので一番面白かった。個人的なNetflixランキング2位。
    • Netflix スタートアップ
      • 韓国のスタートアップの話。恋愛要素が強いけどテック系の話が身近で面白かった
  • 読書

今年買ったもの

  • Switchbot、Alexa
    • アレクサで家電を操作したくて購入した
    • 手が塞がってることが多いので、声で操作できるのめちゃ便利
  • コープ愛媛の生協
    • コープ愛媛は子供が産まれるタイミングから小学校卒業まで配達手数料が無料になってます。注文した食材とか冷凍食品を届けてくれて助かってます。妻が妊娠期間は買い物に行くのも大変なのでたくさん活用したし、子供が産まれたら自炊するのも大変なので助かってます。
  • ソファー
    • カウチソファー買った
  • デロンギ コーヒーメーカ
    • ずっと毎朝ハンドドリップでコーヒー淹れてたけど、時間がどうしてかかるのでAmazonのセールで購入
    • 味も満足してるし、ボタンひとつで勝手に淹れてくれるのでこればっかり飲んでます。あとはスチームミルクでホットドリンク作れるのも良い。
  • 電気ポット
    • ミルク作るのに購入
    • スープとか作る時にも便利
  • 羽毛毛布
    • 昔買った掛け布団を使ってたので羽毛布団を買いました。めちゃ暖かい
  • Keychron Q11 分割キーボード
    • 子供が産まれて大きい車を契約しました。来年納車予定

さいごに

今年は子供が産まれたり、転職したりと大きな変化がある一年でした。

エンジニアとしては、これまでの貯金を使ってるだけの感覚があるので、来年はインプットとアウトプットを圧倒的に増やす年にしたいです。

「フロントエンド開発のためのセキュリティ入門」を読んだ

書籍「フロントエンド開発のためのセキュリティ入門」を読みました。

どういう本か

この本は、Webアプリケーションにおける脆弱性やその対策について、フロントエンドに焦点を当てて解説しています。 Webやセキュリティに関する知識のない人でも理解できるよう、HTTPやオリジン、ブラウザの同一オリジンポリシー、Cookie、DOMといった基本的な用語や概念についても説明されています。

また、ハンズオン形式なので、まずは手元で攻撃を成功させてから対策を入れた結果を確認できるので理解を深めれます。

初学者がわかりやすいように噛み砕いて身近な例で説明していたり、画像や図もあり、とても分かりやすかったです。あと、文章が読みやすくてスラスラ読めました。

ハンズオンはNode.js、Expressベースなので普段はサーバーサイドの開発に触れていなくてもJavaScriptが分かれば、フロントエンドエンジニアがとっつきやすい内容だと思います。

8章では、npnパッケージをはじめとしたライブラリに潜むリスクと対策なども解説しており まさにフロントエンドエンジニアが知っておく内容が幅広く扱われていています。

最近の動向を踏まえた内容

2023年に発売されたということで、自分が追えていない最近の動向を踏まえた変化なども書いてあって学びになりました。 特に、CSPやTrusted Typesあたりは、ちゃんと調べたり、実際に試してこなかったので勉強になりました。

他にも、CookieのSame Site属性やhttp://だとブラウザで警告が出る、Mixed Contentのブロックとか、ここ数年で変化のあったトピックも書いてあり、最新の情報としてキャッチアップできました。

CORP, COEP, COOPあたりは難しかったので、自分で試してみないとなーと思いました。

XSSの章だと、Reactなど、いま使われているライブラリで行われている対策などの解説もあります。

おすすめ

フロントエンドエンジニアとして働いているけど、業務経験が浅く、セキュリティをまだあまり意識してなかった人に特におすすめです。 本書で、Webやセキュリティの基礎的なところも学べるので、気になったトピックを深堀りして、自分が担当してるプロダクトだとどうか?を考えると良さそう。

自分は初学者向けにTechTrainでフロントエンドのメンターをしていますが、HTTPリクエストやデベロッパーツールのNetworkパネルを知らない人も多かったので、そのあたりから、まさに学べて良さそうです。

ある程度、知識や経験があるエンジニアも、最近の動向や変化も踏まえてキャッチアップできるのでおすすめです。

Keychron Q11を購入して分割キーボードデビューした

分割キーボード Keychron Q11を購入しました

ここ数年はずっとHHKBを使っていたけど 肩こりに悩んでいたり、周りの影響で分割キーボードがずっと気になっていました。

そのタイミングでKeychronから分割キーボードが発売されたので、購入しました。

購入したもの

Keychron Q11 QMK Custom Mechanical Keyboard

  • Type: Fully Assembled Knob
  • Color: Carbon Black-B
  • Switched: Gateron G Pro Red

買おうかな〜と思ってたタイミングでずっと売り切れだったので、数日サイト見てたら在庫があったので購入しました。 購入した後、メールが来てDHLのremote areaなので追加で30$ほど払う必要があったので、トータルで35000円くらいになりました。

英語でのメールのやり取りは、ChatGPTを使えばめちゃ楽だった。

使ってみての感想

届いてから、4日ほど使ってるけど、思ってたより快適です。 もうコーディングしてて問題ないレベル。

今回、分割キーボードが初めてなので、不安があったけど、思ったよりは自然にタイピングできてます。 自分があんまりこだわり強くないからかもだけど。

ただ、「B」だけ、これまで右手で入力してたみたいで、左手での入力になかなか慣れずに苦戦してます。 それ意外は、ちょいちょいミスするくらいで大丈夫そう。

なんとなく肩こりにもいい気がするが、本当に効果あるかはもうちょい長期的に見る必要がありそう。

打鍵感もだいぶ良い。

右手の近くにトラックパッドをおいて、すぐにマウス操作できるようになったのも良かったです。

ネガティブな面も少なくて、全体的に購入してよかった。

せっかくなので、カスタマイズとかも色々試してみたい。

その他

Keymapの変更はこのアプリを使ってやってる。

usevia.app

標準でついてるケーブルが短いので、0.5mのものを購入した

2022年の振り返り

今年も1年を振り返っていこうと思います。

金沢に帰った時の紅葉

去年の振り返り

toshi-toma.hatenablog.com

仕事

去年に引き続き、株式会社stand.fmでプロダクト開発に取り組んだ1年でした。 転職してから1年が経ったタイミングでブログも書きました。

note.com

今年は役割がテックリードになったので、機能開発以外に設計やレビュー、実装面でのサポート、仕様の検討などに時間を使うことが多かったです。

ずっと自宅からのリモートワークでしたが、11月に初めて東京のオフィスに行く機会があり、オフラインやっぱいいなって思いました。自分はやっぱり対面でもコミュニケーションが取りたいタイプなので、来年はオフラインでのコミュニケーションも大事にしていきたいなと思っています。

仕事面でのアウトプット

stand.fmにエンジニアとして入社して1年が経った|toshi-toma|note

SentryのPerformance Monitoringを活用する

複業

今年から業務委託でプロダクト開発に関わる形で複業を再開しました。 機能開発だけではなく、リファクタリングなど幅広く取り組めて有意義でした。

開発、学習

最近はプライベートの時間で勉強する。というよりも本業で必要になった技術をプライベートの時間でも調べてキャッチアップする。というケースが主でした。

今年は、GraphQL、GCP、DDD周りについて調べたり本を読んでることが多かったです。

プライベート

今年も引き続き愛媛でのんびり暮らしてるのですが、夏頃に結婚したのでプライベートとしては大きな変化の年でした。 ただ、家で仕事して、空いた時間は複業かNetflixを見てのんびりしてるので、生活は良い意味であまり変わりないです。

あとは、BE:FIRSTというダンス&ボーカルグループにハマってます。おすすめ🥰

今年買ったもの

  • メガネ
    • 普段使ってるメガネは度が強く、体質的にも頭痛の日が多かったので、試しに度が弱いサブメガネを買ってみたら、目への負担が減ってよかったです
  • 冷蔵庫
    • これまでは一人暮らし用の冷蔵庫を使っていたけど、限界を感じたので、三菱の大きい冷蔵庫を買ってストレスフリーになりました
  • ネックウォーマー、マッサージガン
    • PC & デスクワークなので、首や肩のコリがひどく、ネックウォーマーとマッサージガンを買ってみました。コリを感じる前に定期的に使うのが重要な気がします
  • たこ焼き器
    • 炎たこっていうガス火のたこ焼き器を買いました。家でも最高に美味しいたこ焼きが食べれます
  • 布団乾燥機の購入
    • 冬は布団が冷たくて辛いので、年末に買ってみた。まだ届いてないので来年使ってみる。

さいごに

最近は年齢的にもプライベート面で変化が多いタイミングな気がしてます。 仕事もプライベートも頑張るぞ💪

2021年の振り返り

今年も1年を振り返っていこうと思います。

本州から四国に行く電車からの景色
本州から四国に行く電車からの景色

去年の振り返り

toshi-toma.hatenablog.com

仕事

今年は転職したので、仕事面での変化が大きかったです。 2021年の3月にサイボウズ株式会社を退職して、株式会社stand.fmに入社しました。

stand.fmはもともとユーザーとして使っていたこともあり、モチベーション高くプロダクト開発ができています。

プロダクトとしてはアプリがメインなので、これまでWebフロントエンドをメインで開発していた自分としては不安が大きかったですが、すべてJavaScript/Reactベースなのでスムーズに開発できました。 技術的にも、Webフロントエンド以外にReact Nativeでのネイテイブアプリ、Node.jsでのバックエンド開発、GCPk8sなど新しいことをキャッチアップすることが多くて学びが多い一年でした。

あと、最近は意思決定する機会が増えてきました。次の壁にぶつかってる感じがして悩むことも多いですが楽しいです。

来年はstand.fmがもっと多くの人に使ってもらえるようにとにかく頑張る💪

仕事面でのアウトプット

stand.fmのAlgoliaを活用した検索機能の実装|toshi-toma|note

stand.fmの最近の取り組み: アプリ起動速度の改善/improvement-of-speed-startup-app - Speaker Deck

stand.fmのTypeScriptへの移行と活用/migrating-to-typescript-standfm - Speaker Deck

複業

TechTrain

引き継ぎTechTrainでメンターをやってます。面談以外にもReactを学ぶための教材の開発をしました。

prtimes.jp

フロントエンドの業務委託

今年の3月ごろまでは業務委託でフロントエンドの開発をしました。転職すると精神的・時間的な余裕がなくなりそうだったので、転職のタイミングで複業は一度辞めることにしました。

いまは落ち着いてきたので、来年再開できたらいいなと思ってます。

開発、学習

3月は有給消化期間だったので、次の会社で使いそうな技術を勉強したり、特定の技術を深ぼったりしてのんびり過ごしました。

転職してからはプライベートの時間で勉強することが減りました。たまに技術書読んでるくらいかな。

プライベート

今年は引き続き愛媛でのんびり暮らしてるので、大きな変化はなかったです。ただ、愛媛県内で広い家には引っ越したので、リモートワークしてる身としては最高です。 Netflixを契約して、プライベートの時間はドラマやアニメを見ることが多かったです。韓国ドラマが特に面白いです。

ずっと家にいて運動不足感があるので、リングフィットしたり、最近はジムに通い始めました。 あと前よりも体の調子を整えたい欲が出てきて整体に通うようになりました。

なんだかんだ実家の金沢に3回も帰ってました。

今年買った/契約したもの

  • 食洗機
    • 家事の時間を減らしたくて食洗機を買いました。洗い物から解放されて最高です。
    • 愛媛は車が無いと行動範囲が限られるので車をかいました
  • テレビ
    • 大きめのテレビを買いました。大きいとそれだけで映像が楽しいです。テレビ見る時間が増えたので複雑
  • 洗濯機
    • ドラム式の乾燥機付き洗濯機を買ったことで、服を干したり取り込むことから開放されました。とにかく最高です
  • Netflix
    • Netflixを契約しました。HuluやAmazon Primeも見れるけど、Netflixのオリジナルコンテンツばかり見てます
  • iPhone 13 Pro
    • カメラが最高です
  • PostCoffee
    • コーヒーのサブスクです
    • 最近は朝にコーヒー淹れるのにハマってるので、休みの日には普段とは違う豆を使えて良いです
  • 髭脱毛
    • 髭を剃るのが面倒なので通い始めました。結構痛い。
  • nosh
    • おいしい冷食
    • ご飯用意するのが面倒な時に使ってます

さいごに

今年は仕事面での変化が大きかったです。 来年はエンジニアとして成長しつつ、プライベートももっと充実させれるように頑張る。

WYSIWYGエディタ TinyMCEを使った開発

リッチテキストエディタ及びWYSIWYGエディタのライブラリは世の中にたくさんあります。

ourcodeworld.com

最近、TinyMCEというWYSIWYGエディタを使った開発をしました。とても高機能で使いやすく、基本的には無料で利用することができます。

www.tiny.cloud

ドキュメント

ドキュメントは、以下のページを見ることになります。

Documentation | Docs | TinyMCE

ReactプロジェクトへTinyMCEの導入

自分が開発したのは、Reactのプロジェクトだったので、@tinymce/tinymce-reactというパッケージを利用しました。

github.com

導入はとても簡単で、以下の通りに、<Editor>コンポーネントを利用するだけです。

import { Editor } from "@tinymce/tinymce-react";
const App = () => {
  const [doc, setDoc] = useState("");
  const onChange = (value) => {
    setDoc(value);
  };
  return (
    <Editor
      initialValue={doc}
      apiKey={process.env.REACT_APP_TYNY_MCE_API_KEY}
      init={{
        height: 800,
        menubar: false,
        branding: false,
      }}
      onEditorChange={onChange}
    />
  );
};

API Key

<Editor>コンポーネントには、apiKeyを渡す必要があります。

API Keyは、Tinyのサイトで会員登録すれば取得できます。

https://www.tiny.cloud/

Approved Domains

Tinyのサイトにログイン後、「Approved Domains」を設定する必要があります。デプロイするドメインを登録する必要があります。 localhostはデフォルトで許可されているので、デプロイするまでその必要性を知りませんでした。

日本語化

エディタのパーツを日本語化することが可能です。

https://www.tiny.cloud/docs/advanced/creating-a-plugin/#languagelocalization

日本語化は、以下のページでjaファイルをダウンロードして、デプロイする際にtinymce/langs/ja.jsとして配置しました。

www.tiny.cloud

あとは<Editor>のlanguageを指定すればOKです。

<Editor
  initialValue={doc}
  apiKey={process.env.REACT_APP_TYNY_MCE_API_KEY}
  init={{
    height: 800,
    menubar: false,
    branding: false,
    language: "ja",
  }}
  onEditorChange={onChange}
/>

プラグイン

TinyMCEの魅力の一つに豊富なプラグインがあります。Open source pluginsであれば、無料で利用できます。

www.tiny.cloud

導入もとても簡単で、pluginsプロパティに組み込みたいプラグイン名を配列で指定するだけです。

const App = () => {
  const [doc, setDoc] = useState("");
  const onChange = (value) => {
    setDoc(value);
  };
  return (
    <Editor
      initialValue={doc}
      apiKey={process.env.REACT_APP_TYNY_MCE_API_KEY}
      init={{
        height: 800,
        menubar: false,
        branding: false,
        language: "ja",
        plugins: ["fullscreen", "link", "table", "lists"],
      }}
      onEditorChange={onChange}
    />
  );
};

ツールバー

表示するツールバーの機能もtoolbarプロパティで指定することができます。こちらは文字列で指定します。|ツールバー上での区切りUIの指定です。

const App = () => {
  const [doc, setDoc] = useState("");
  const onChange = (value) => {
    setDoc(value);
  };
  return (
    <Editor
      initialValue={doc}
      apiKey={process.env.REACT_APP_TYNY_MCE_API_KEY}
      init={{
        height: 800,
        menubar: false,
        branding: false,
        language: "ja",
        toolbar:
          "undo redo | formatselect | fontsizeselect | bold italic",
      }}
      onEditorChange={onChange}
    />
  );
};

画像の指定

エディタ内での画像指定にはImage Pluginを利用します。

www.tiny.cloud

画像選択時に、アプリケーション内の画像選択ダイアログを利用したい場合があります。 その場合はfile_picker_callbackを利用すると実現できます。このcallbackはTinyMCE上で画像選択UIのクリック時に発火します。 第一引数のcallbackに任意のURLを渡すと、それがエディタ上に挿入されます。

なので、無理やりですが、callback関数をstateに保持しておき、ダイアログを表示、ダイアログで画像選択時にstateで保持したcallback関数に選択したURLを渡して実行する。といったアプローチで実現することができました。

const App = () => {
  const [doc, setDoc] = useState("");
  const onChange = (value) => {
    setDoc(value);
  };
  return (
    <Editor
      initialValue={doc}
      apiKey={process.env.REACT_APP_TYNY_MCE_API_KEY}
      init={{
        height: 800,
        menubar: false,
        branding: false,
        language: "ja",
        toolbar: "undo redo | formatselect | fontsizeselect | bold italic",
        file_picker_callback: function(callback, value, meta) {
          if (meta.filetype === "image") {
            // 任意の処理
          }
        },
      }}
      onEditorChange={onChange}
    />
  );
};

Full Page Plugin

基本的には、ブログ記事のエディタのような使われ方が多いですが、Webページ(HTML)を編集するエディタとしても利用できます。 そういった場合に、Full Page Pluginを利用します。

www.tiny.cloud

このプラグインを利用しないと、HTML文字列をエディタに渡しても、head要素などが消されてしまい、bodyの中しか編集できないようになっています。

このプラグインを利用することで、head要素などがそのまま組み込まれた状態で編集することができます。

ただし、いくつか注意点があります。

body_id, body_class

TinyMCE上では、html要素やbody要素はTinyMCEが生成するものに書き換えられてしまいます。 なのでbody要素に特定の属性を指定していたHTML文字列を渡しても、エディタ上では、その属性が消えてしまいます。

body要素のclassやidは以下の設定で、追加することが可能です。なので、事前にHTML文字列をパースして、idとclassを抜き出してエディタに設定として渡すといった対応が必要な場合があります。

https://www.tiny.cloud/docs/configure/content-appearance/#body_id https://www.tiny.cloud/docs/configure/content-appearance/#body_class

JavaScript無効化

TinyMCE上では、scriptタグがすべて無効化されます。主にセキュリティの目的なので、設定で無効化できる挙動でもありません。

github.com

document_base_url

JavaScriptの読み込みや実行はできませんが、CSSファイルは読み込めます。その際、リンクに相対パスを指定している場合、document_base_urlを指定することで、任意の場所で配布されているファイルにリクエストが可能です。

https://www.tiny.cloud/docs/configure/url-handling/#document_base_url

コンテンツの書き換え

TinyMCEが自動でHTMLの中身を書き換えてしまう場合があります。 基本的に中身を変えてほしくない場合はverify_htmlconvert_urlsをOFFにするのがおすすめです。

React Queryを使った開発

最近、React QueryやSWRといった、キャッシュ機構をもったHooksを使う開発が多くなっています。

自分も、ReactのプロジェクトでReact Queryを採用しました。その過程で迷ったことなどのメモです。

react-query.tanstack.com

React Query vs SWR

React QueryとSWRは似たライブラリです。 自分もどちらを採用しようか迷ったタイミングで、調べてみました。

参考

zenn.dev

scrapbox.io

ただ、調べてみても、できることは両者大きな違いが無さそうでした。

最終的には、React QueryにはDevToolsがあり、SWRには無い。という点でReact Queryを選択しました。 DevToolsでは、どんなキーでどんなデータがキャッシュされているのか確認することができます。

github.com

React Queryについて

React Queryの何が良いのかについて触れておきます。

Reactでの開発によくある実装として、以下のようなものがあります

  1. データを保持するstateを定義する
  2. useEffectでAPIデータ呼び出しを行う
  3. API呼び出し中はローディングを表示する
  4. API呼び出しが終わったら、ローディングを終了して、結果をstateに更新する
  5. 更新されたstateをもとにコンポーネントを表示する

コードで表すと、以下のようになります。

const App = () => {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetchData().then((res) => setData(res));
  }, []);

  if (!data) {
    return <Loading />;
  }

  return <MyComponent data={data} />;
};

もし、Reduxを使っていた場合は、Storeに取得したデータを格納します。

ここで、APIのレスポンスを格納するためのStateやStoreを用意するのではなく、APIのレスポンスをキャッシュすればコンポーネントがStateを定義しなくて良いよね。というアプローチをReact Queryが提供してくれます。

React Queryを使った場合は以下のようになります。

const App = () => {
  const { data } = useQuery("fetch-data-key", fetchData);

  if (!data) {
    return <Loading />;
  }

  return <MyComponent data={data} />;
};

useQueryというHooksにキャッシュのキーとデータフェッチ用の関数を渡します。そうすると、fetchDataの結果をキャッシュします。 すると、Appコンポーネントが再レンダリングされる際はキャッシュされたデータをHooksが返します。

もしキャッシュが無いと、Appコンポーネントの再レンダリングごとにAPI呼び出しが発生しそうに見えますが、キャッシュのおかげでそのような問題もありません。

APIからデータを取得して、それを表示するのがメインのアプリケーションであれば、Reduxなどは使わずにReact Queryだけで十分に感じました。

自分の場合は、管理画面を開発したので、このユースケースにとてもマッチしており、シンプルなコードで開発を進めることができました。

React Queryの導入

ここからは React Queryの導入について説明します。

まずはパッケージをインストールします。

$ npm i react-query

次は、QueryClientProviderを設定します。また、DevToolsを利用する場合はReactQueryDevtoolsを配置します。 QueryClientProviderに渡しているQueryClientオブジェクトには、細かい設定を行えます。 例えば、どれくらいの期間はキャッシュから返すのか?など。

import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 1 * 60 * 1000, // 1分間はキャッシュから返す
      refetchOnWindowFocus: false, // ウィンドウにフォーカスしたタイミングでデータを再取得しないように
    },
  },
});

const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
      <ReactQueryDevtools initialIsOpen={false} />
      <MyComponent />
    </QueryClientProvider>
  );
};

あとは、各コンポーネントuseQueryといったHooksを利用するだけです。

useQuery

最後に、主に利用しているuseQueryについて説明します。他にもいくつかHooksが用意されていますが、自分は使わなかったので触れません。

useQueryの第1引数には、キャッシュのキーを指定します。このキーが同じ場合は、キャッシュからデータが返されるので、予期せず違うAPI呼び出しなのに同じキーを指定しないようにしましょう。

第2引数には、Promiseを返す関数を指定します。自分はaxiosと組み合わせて利用しました。

Query Cancellation | React Query | TanStack

const App = () => {
  const { data } = useQuery("fetch-data-key", fetchData);

  if (!data) {
    return <Loading />;
  }

  return <MyComponent data={data} />;
};

第1引数には配列を指定することも可能なので、ページネーションがあるような場合に便利です。

const { data } = useQuery(["fetch-data-key", pageIndex], () =>
    fetchData(pageIndex)
);

任意のタイミングでデータを再取得したい場合のために、refetch関数も用意されています。

const App = () => {
  const { data, refetch } = useQuery("fetch-data-key", fetchData);

  if (!data) {
    return <Loading />;
  }

  return <MyComponent data={data} refetchData={refetch} />;
};

staleTime

デフォルトでは、staleTimeが0になっているので、キャッシュを使わずに毎回APIからデータを取得します。 必要に応じて、どれくらいの時間キャッシュから返すのかを指定することになります。

Initial Query Data | React Query | TanStack