2
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.

if文の中でuseMemoを使ったときの面白い挙動

Last updated at Posted at 2022-02-22

if文の中でuseMemoを使ったときの面白い挙動

はじめに

if文の中でhooksを使ったらダメなのはみなさんご存知ですよね。
もしif文の分岐でhooksが呼ばれる回数が変わったら以下のようにエラーがでて怒られます。
image.png

もしif文の分岐があってもhooksが呼び出される回数や順番に変更がなければどうなるのでしょうか?
そのときの面白い挙動を紹介します。

環境

"react": "^17.0.2",

やってみた。

以下のようなプログラムを書きます。

/* eslint-disable react-hooks/rules-of-hooks */
import React, { useMemo, useState } from "react";
import "./App.css";

function App() {
  const [flag, setFlag] = useState(true);
  let memo1 = 0;
  let memo2 = 0;
  let memo3 = 0;

  if (flag) {
    memo1 = useMemo(() => 1, []);
  }

  memo2 = useMemo(() => 2, []);

  if (!flag) {
    memo3 = useMemo(() => 3, []);
  }
  const value = { memo1, memo2, memo3 };

  return (
    <div className="App">
      <button onClick={() => setFlag((_flag) => !_flag)}>Toggle</button>
      <br />
      {JSON.stringify(value)}
    </div>
  );
}

export default App;

memo1,memo2,memo3はそれぞれ0で初期化されており、
flagtrueの場合、memo1useMemoからの値を参照し1になり、flagfalseの場合、memo3からの値を参照し3になる想定です。memo2は常にuseMemoからの値を参照し2になります。
flagの初期値はtrueでToogleボタンをクリックするとtruefalseが入れ替わります。

image.png

初回は上記のような表示になります。
memo1,memo2,memo3は以下の値です。
{"memo1":1,"memo2":2,"memo3":0}

別に問題なさそうですね。
ではToogleボタンをクリックしてflagfalseにします。

image.png

おや...!?
予想だと{"memo1":0,"memo2":2,"memo3":3}になると思ったんですが。
memo2に値を代入しているuseMemo常に2を返しているはずなのに値が1になっています。またmemo3に値を代入しているuseMemoも常に3を返しているはずなのに値は2になっています。

これはおもしろいですね。

考察

関数の外側からはuseMemoがどこで呼ばれたかではなく、何回よばれたかという情報しかわからないからこういう挙動なんだろうと思う。もしどこで呼び出したかまでわかるようにするとしたらkeyみたいな概念が必要と思われる。きになってReactのリポジトリ見にいったけどさっぱりわかりませんでした。どこ読めばわかるかわかった人いたら教えてください💕

2
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
2
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?