useEffect, useCallback, useMemoに関しての使い分け

Claudeに課金をしたので、先日より取り組んでいるElectron製のアプリをちまちまと助けを借りながらいじっているのですが、

まずは、提示された内容を元に書き写すような形で進めています。

その中で、AIあるあると言えばあるある何でしょうけれど、生成されるコードがコロコロ変わる問題にぶち当たっています。

結局のところ、目的を達成する上でプログラミングの書き方としては複数のやり方があって、その背景をAIに伝えない限りはどの手法が適切なのかはわからず、その生成されるコードが変わるわけですね。

言葉で言ってしまえば、そりゃそうなんだけど、なかなかのストレスです。
完全に任せるわけではない、AIサポートの開発における難しさを感じますね。。。

こういうものを見ていると、結局コードに関しての知識は必要になりそうだな、という気がしてきます。

というわけで、今回は自分の学習記録として、useEffectとuseCallback。そして調べているうちに出てきたuseMemoに関して書いてみようと思います。

useEffect – 副作用の管理

特徴

  • コンポーネントのレンダリング後に実行される
  • DOM操作、データフェッチング、購読、タイマーなどの副作用を扱う
  • クリーンアップ関数を返すことで、コンポーネントのアンマウント時や依存配列の値が変わる前に実行される処理を定義できる

使用例

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

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 副作用: APIからデータをフェッチ
    setLoading(true);

    // userIdが変わるたびに新しいユーザーデータを取得
    fetch(`https://api.example.com/users/${userId}`)
      .then(response => response.json())
      .then(data => {
        setUser(data);
        setLoading(false);
      });

    // クリーンアップ関数
    return () => {
      // コンポーネントのアンマウント時やuserIdが変わる前に実行
      console.log('User profile cleanup');
    };
  }, [userId]); // 依存配列: userIdが変わったときだけ実行

  if (loading) return <div>Loading...</div>;
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

いつ使うべきか

  • 外部データの取得
  • イベントリスナーの設定と解除
  • DOM要素の直接操作
  • タイマーの設定とクリア
  • 外部サービスへの購読と解除

useCallback – 関数のメモ化

特徴

  • 関数をメモ化し、不要な再生成を防ぐ
  • 依存配列の値が変わるまで、同じ関数インスタンスを保持する
  • 子コンポーネントに渡す関数のパフォーマンス最適化に役立つ

使用例

import React, { useState, useCallback } from 'react';

// 子コンポーネント(React.memoでメモ化)
const ExpensiveList = React.memo(({ items, onItemClick }) => {
  console.log('ExpensiveList rendered');
  return (
    <ul>
      {items.map(item => (
        <li key={item.id} onClick={() => onItemClick(item.id)}>
          {item.name}
        </li>
      ))}
    </ul>
  );
});

function ItemManager() {
  const [items, setItems] = useState([
    { id: 1, name: '項目1' },
    { id: 2, name: '項目2' },
  ]);

  const [count, setCount] = useState(0);

  // useCallbackを使用して関数をメモ化
  const handleItemClick = useCallback((id) => {
    console.log(`Item ${id} clicked`);
  }, []); // 空の依存配列: 関数は再作成されない

  return (
    <div>
      <h1>アイテム管理</h1>
      <ExpensiveList items={items} onItemClick={handleItemClick} />
      <div>
        <p>カウント: {count}</p>
        <button onClick={() => setCount(count + 1)}>
          カウント増加
        </button>
      </div>
    </div>
  );
}

いつ使うべきか

  • `React.memo`でラップされた子コンポーネントに関数を渡す場合
  • `useEffect`の依存配列に関数を含める場合
  • イベントハンドラーが複雑で、不要な再作成を避けたい場合
  • 関数が他のフックの依存関係になっている場合

useMemo – 値のメモ化

特徴

  • 計算結果をメモ化し、不要な再計算を防ぐ
  • 依存配列の値が変わるまで、前回の計算結果を再利用する
  • 計算コストが高い処理の最適化に特に役立つ

使用例

import React, { useState, useMemo } from 'react';

function ExpensiveCalculation({ numbers }) {
  const [count, setCount] = useState(0);

  // 計算コストが高い処理をuseMemoでメモ化
  const sumResult = useMemo(() => {
    console.log('Heavy calculation running...');
    // 重い計算の例
    return numbers.reduce((total, num) => {
      // 人為的に処理を重くする
      for (let i = 0; i < 1000000; i++) {}
      return total + num;
    }, 0);
  }, [numbers]); // 依存配列: numbersが変わった時だけ再計算

  return (
    <div>
      <h2>計算結果: {sumResult}</h2>
      <p>カウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        カウント増加(計算には影響しない)
      </button>
    </div>
  );
}

function App() {
  const [numbers, setNumbers] = useState([1, 2, 3, 4, 5]);
  return (
    <div>
      <ExpensiveCalculation numbers={numbers} />
      <button onClick={() => setNumbers([...numbers, numbers.length + 1])}>
        数字を追加
      </button>
    </div>
  );
}

いつ使うべきか

  • 計算コストが高い処理の結果をキャッシュしたい場合
  • レンダリングごとに再生成したくないオブジェクトがある場合
  • 大きな配列やオブジェクトの変換や加工を行う場合
  • コンポーネントの再レンダリングが頻繁に発生する場合

まとめ

結局のところ、どこまでキャッシュさせることが可能な内容何だっけ?ってところなんでしょうね。

計算コストが高くても、再レンダリングが頻繁に発生しようとも、表示内容が再計算必要なものであればuseEffectにするしかないんだろうし。。。くらいに覚えておくことにします!

トイレとの仁義なき戦い

詰まりました

我が家には1階と2階にトイレがあるのですが、2階のトイレが詰まり、流れていかない状態に・・・

実は、過去にも一度経験をしていてその時にアイテムを手に入れました

【専門家が推薦】GANGAN パイプクリーナー ワイヤー 回転式 排水管 排水溝 つまり ワイヤーブラシ 5m 排水溝 詰まり 解消 洗浄 掃除 家庭で使える 業務用清掃ブラシ 手袋 保管袋 スポンジ付き

前回、これでワシャワシャやることによってなんとか詰まりを取ったことはあるのですが、今回はうまくいかず。。。
しかも流さないと水は溜まっていきついには溢れてしまうので、それはもうひどい状態に・・・。

本当、この作業は精神を削られます

妻が、ワイヤーじゃなくてスッポンだ!というので、急遽ホームセンターまで行き、スッポンを購入

SANEI(旧社名:三栄水栓製作所)真空式パイプクリーナー 大型洋式トイレ用 詰まりを解消 大・小 ゴム付き 強力吸引力 PR8700-L

これでワシャワシャやっていたのですが、何故かそこで水が流れ始めてまた溢れてしまう・・・。

もう、私のライフはゼロよ・・・

それでも、何度となくスッポンとワイヤーで挑戦をし続けたことでなんとか詰まりを解消することができました・・・と思う。

業者呼んだら、絶対高く付く!と思っているので必死になったものの、もはや今日は何もやる気力起きず・・・。
何をやっているんだか。。

マネジャーが健全なハードワークを続けるための心得 – HBR4月号

HarvardBusinessReviewの4月号。なかなか読み進めることができていませんが、インタビュー記事として掲載されている「マネジャーが健全なハードワークを続けるための心得」が面白かったです

DIAMONDハーバード・ビジネス・レビュー20 2025年4月号 [雑誌]特集「持続可能なハードワーク」 DIAMONDハーバード・ビジネス・レビュー

今月号の特集は「持続可能なハードワーク」ということで、ハードワークすることに関して焦点を当てています

ともすると、今の主流の考え方はハードワークそのものを否定しかねない形になっているように感じます。
もちろんパワハラ的なハードワークは論外ですし、一昔前の残業が常態化した状態を懐かしんでいるわけでもないですが、本インタビューでも書かれているように、「成果を出すためのハードワーク」は必要に感じるシーンはあります。

もちろん、ハードワークをしなくても成果が出せるように動くということも大事なのでしょうけれど、ある程度の競争が生まれる業務においてそれで成果を出せるのか。勝つことができるのかは別問題ではないかと。

腹落ちハラスメント

インタビュー記事を読んでいて、面白い言葉だたな、と思ったのは「腹落ちできないので、この仕事はしません」というような話題。

では、若手が未知な業務を習得することにおいて体感・体験しない状態で本当に腹落ちなんてできるのか?実践を通してようやく論理と繋がるのではないかという考え方でした。

やりたい仕事だけやっていて成果を出せたり業務全体が回ればそれは一番いいのかもしれませんが、実際のところそれでは仕事が回らないこともありますし、そんな都合のいい仕事ばかりではない。

腹落ちまではいかなくても、どうやってそれらを伝えるのか。
伝え方の工夫で。。。となっていますが、正直結構難しいな、と思うわけなんですよね。
ハードワークという一言で語られていますが、どこからがハードワークなのか。そもそも何をハードとして捉えるのかも人によってまちまちです。

このあたりは教育の難しさを感じずに入られませんし、その人のライフステージによっても変わってきそうです。

嫌になっちゃうテーマですね。。。

キングダム 75発売

キングダムの75巻が発売されました

キングダム 75

前回、韓の南陽を攻略したところまで進み、この巻からは韓國王都新鄭に向けた戦いが始まります。

74巻がどちらからと言うと政治面や前哨戦だったので、なんだか久しぶりの大戦な気がします。

韓攻略自体は実現しないと話が進まないので、成功する気がしますがあとは漫画としてどこまで盛り上げるか。。。ですかね。
すでに将軍としての才覚を出している信をこの先どう見せていくのか。

楽しみです

疲れてます

ここのところ、夜寝る時間もちょっと遅かったり朝早かったりで、睡眠の質が下がっていました。

それもあって、トレーニングレディネスやトレーニグステータスは悪い値が続いている、、、

今日は早いところ眠りにつこうと思います。

Tailwindcssの適用にてんやわんや

Electronのプロジェクト構成として、Next.jsをフロントエンドに選択。
CSSとしてはTailwindcssを適用しようとしていたのですが、見様見真似でやっているものの、動いているコードを見る限り正常にTailwidがあたっているように見えない。

ということで、もう一度インストールから見直してみることに。

$ npm install -D tailwindcss autoprefixer postcss

インストール自体は上記コマンドで問題なくインストールできているようです。
これに、初期化するコマンドが必要となるのですが

$ npx tailwindcss init -p
npm error could not determine executable to run
npm error A complete log of this run can be found in: /XXXXX

というようにエラーが出ていることがわかりました。

おかしい。。。Claudeに聞いてみてもセットアップの仕方は上記コマンドで問題ないはずなのですが、、、と調べてみるとどうやらtailwindcssのv4系ではセットアップ方法が変わったようで、上記のコマンドはv3系のもののよう。

そんなわけで、一旦インストールするtailwindcssをv3系にしてみます

$ npm install -D tailwindcss@3.4.17 autoprefixer postcss
$ npx tailwindcss init -p

上記でエラーが解消されました。

v4系のセットアップは、ViteかPostCSSなどによってやり方が変わっているよう。

もう、頭から引っかかりまくっているので大変です。。。
やっぱりフロントエンドは中途半端に手を出すときっついです。

魔女の宅急便 2

魔女の宅急便の2巻であるキキと新しい魔法を読んだ

新装版 魔女の宅急便 (2)キキと新しい魔法 (角川文庫)

キキがコリコの街に来て2年目を書かれた作品。
基本的にはいろいろな宅急便のしごとを通してキキの成長を描くという軸は変わらず、仕事に対する向き合い方だとかそういったことを考えるサマが書かれていた。
そして、成長していくことで過去に挑戦しなかったことへの再挑戦。

比較的読みやすい言葉で書かれているので、子どもが読むのにちょうどいい内容でもあるかもしれないな、と思う一方で、派手な展開に慣れてしまっていると読んでくれるかな?と思うような内容でもあった。

というか、修行の旅は1年で実家に帰るわけではなくそのまま継続されるんだ。
このままコリコに居続けることになるのか、なにかイベントが有って移住したり実家に変えたりするのか。
このシリーズは6巻まであるので、これからどんな物語が続くのか。
気になる一方ですごい気になるというわけでもなく、気が向いたときに手に取る感覚で読み進めていければと思う。

次の3巻では新たな魔女が登場予定。
どうなるでしょう

新装版 魔女の宅急便 (3)キキともうひとりの魔女 (角川文庫)

エール

今日は珍しく会社のメンバーと飲み会。

と言っても私は酒は全然ダメなのでジンジャエールですが。
近々退職をする後輩も混じりで気兼ねない時間を過ごしました。

もちろん相手にとっていい時間になったかはわかりませんが、今後も頑張って欲しいところです。

組織に所属していれば、何かしら不満はあるものだし綺麗事ばかりではないのは分かりつつも、その中で自分はどうあるべきかは歳を重ねても正解はわかりません。

組織を変えていくと言うのが格好いいところではあるけれど、その組織にこだわる理由もなければ、より自分にとっていい組織を目指して転職するのもごくごく合理的です。

全てが糧になると考えて前を向くしかないんですけどね。

何にせよ、いい繋がりを保てれば嬉しいとは思います。

なんかそんな事をふと思いながら帰路についてます

ストレスレベルが高いです

Garmin先生を付けていて面白いな、と思うのはBody Batteryの値です

ちなみに、これが今日のもの。
モヤモヤが溜まってしまっていたので夜にも軽く走りに行きました。

日中帯は在宅で仕事をしていたにも関わらず、常にストレスを感じていたとGarmin先生はおっしゃるわけです

このストレスレベル。
何を持って測定しているのだろう?と

機能と特性:ストレスレベル計測について
https://support.garmin.com/ja-JP/?faq=WT9BmhjacO4ZpxbCc0EKn9

上記公式ページを見ると、下記のようです

各心拍間の可変的な時間の長さは、体の自律神経系によって調節されます。拍間の変動が小さいほどストレスレベルが高いことを意味し、変動が大きいほどストレスが低いことを示します。

正直ここのところ、忙しいというわけではないですがストレスは結構高い状態が続いています。実はHRVステータスもバランスゾーンを超えてアンバランスになってしまっています

うーん、ストレスは感じてはいるものの、実際にこういう風に数値やグラフとして示されるとより意識してしまいますね。

瞑想でも取り入れたほうがいいかもしれないが、そもそものモヤモヤの原因をなんとかしないとどうしようもないですね。。。

坂道トレーニングに挑戦

近所に坂道があったなぁと思い、今日はそこで坂道ダッシュをしてみた。
昨日にもGarmin先生メニューの無酸素を実施したので連日の無酸素になりそうだけれど、今日の目的としてはどれくらいの距離なのか?というところ。

Garmin先生のメニューには当然坂道ダッシュというものはないので、マニュアルでのラップを記録する形になります。

やってみると、ちゃんとランと回復を分けて記録してくれていてわかりやすい。
Garmin先生の無酸素メニューでも40秒くらいのダッシュを求められていたので、比較的いい内容だったのではないだろうか。

40秒前後のダッシュで距離としては200mくらい。
高度としては38m付近から53m付近まで上昇したので勾配としては7.5%、4.3度というところ。
うーん、まぁまぁの坂というところですかね。

距離200mという部分はもう少し延ばせそうですが、勾配に関しては場所を変えるしかないですね。

連日の無酸素トレーニングになってしまったので5本で終えましたし、最後は持たなかった!
距離を伸ばしたり、もっと厳しい坂に挑戦したりとして足を鍛えていきたいところです。