LoginSignup
0

More than 3 years have passed since last update.

久々reactでの個人的ハマったポイント備忘録

Last updated at Posted at 2021-02-14

reactとreduxを一気に学習すると最初はわかったつもりでも
忘れたり、こんがらがったりすることがありました。
その中での備忘録です。

getElementByIdでオブジェクトが取れない

自分の場合はコンポーネントのライフサイクルを完全に忘れてしまっていました。
コンポーネントのライフサイクルをざっくり書くと

コンポーネントがマウントされて

再レンダーされて

アンマウントされる

というものです。

errorCompleteGet.jsx

const ButtonText = () => {
    const buttonName = document.getElementById("button").innerText;

    const getButtonName = () => {
        alert(buttonName)
    }

    return (
        <section>
            <button onClick={() => {getButtonName()}} id="button">ボタン</button>
        </section>
    )
}

getElementByIdの1行はreturnの前に実行されてしまうので例外が走って


TypeError: document.getElementById(...) is null

となってしまいます。
こうなるとreturnの後、つまりコンポーネントライフサイクルでいうと
マウントされた後に実行したいとなるわけですが
そこで最近であればuseEffect※1を使う場面となります。
※1react hooksの関数

CompleteGet.jsx

const ButtonText = () => {

    let buttonName = ""; //1

    const getButtonName = (buttonName) => {
        alert(buttonName) //4 クリックされた時点で実行。クリックされなければ実行されない
    }

    useEffect((event) => {
        buttonName = document.getElementById("button").innerText; //3
    },[]);

    return ( //2
        <section>
            <button onClick={() => {getButtonName(buttonName)}} id="button">ボタン</button>
        </section>
    )

}

useEffectの詳細は割愛させていただきますが
上記のようにuseEffectのコールバック関数で実行することで
コンポーネントマウント後にgetElementByIdが実行されるので
オブジェクトが取得できるようになります。
コメントアウトの番号は実行される順番になります。

無限ループが起こる

関数でコンポーネントを定義していてreturnの中でクリックイベントを発生させたい時。
具体的には以下のような形で書くと無限ループが発生するようになりました。

errorCounter.jsx

const CounterComponent = () => {

    let [count, counter] = useState(0);

    const countUp = () => {
        counter(count + 1);
    }

    return (
        <section>
            <button onClick={countUp}>カウント|{count}</button>
        </section>
    )
}

export default CounterComponent

以下エラーメッセージです。

error.console

Too many re-renders. React limits the number of renders to prevent an infinite loop.

ここでポイントとなるのが前述ソース内の

onClick.jsx

onClick={countUp}

この書き方だとcountUp関数はクリックしなくても最初コンポーネントマウント時に実行されてしまうんですね。
するとsetStateする関数であるcounterが走る
そうなるとstateが変化したので再レンダー処理が走る(上記ソース内でのreturn文)
つまり
countUp

counter(stateがセットされ再レンダーの合図)

return(再レンダー)

countUp


となりめでたく無限ループが完成します。
そこで対策として

okOnClick.jsx

onClick={() => {countUp}}

として即時関数でラップしてあげると
クリックされて初めてcountUpが実行されます。

所感

学習時は理屈がわかって、写経して動いても
実際自分で組み立てて使う時にハマり
わかってないところが浮き彫りになりますね。
1つ1つ丁寧に理解することも復習時には大事だと実感しました。

参考サイト

無限ループのところで参考にさせていただきました。ありがとうございます。

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
0