【React】三項演算子でモーダル開閉するとuseStateの値が空になる原因と対処法

Reactでモーダル(ポップアップ)画面を作成していたところ、モーダルを開いて情報入力した値をuseStateで更新しモーダルを閉じる動作を行うとuseStateで更新したはずの変数が空になります。今回はこの挙動の対処法をメモしておきます。

現象

  • 1.モーダルを開く
  • 2.モーダル上で情報を入力
  • 3.useStateで値を更新
  • 4.モーダルを閉じる動作を行う
  • 5.useStateで更新したはずの変数が空になる(why?)

原因

三項演算子を使ってモーダルの開閉を行なっていたのですが、開閉時の再レンダリングで変数がリセットされるのではないかと思います。

対処法

モーダルの開閉に三項演算子は使わないことで解決できます。(モーダルに限らず、三項演算子で出しわけしているコードの中で変数を書き換えるのは控えた方が良い気がします。)

以下、適当に書いたので動くかは分かりませんが、サンプルコードを記載しておきます。意図が伝われば幸いです。

NG例

import React, { useState } from "react";
/*--------------------------------------------------
親コンポーネント
--------------------------------------------------*/
const Page = () => {
  const [isShow, setIsShow] = useState(false);
  const [text, setText] = useState("");
  const openModalHandler = () => {
    setIsShow(!isShow);
  };
  const updateText = (newText: string) => {
    setText(newText);
  };
  return (
    <div>
      <button
        onClick={() => {
          setIsShow(!isShow);
        }}
      ></button>
      {/*NG:三項演算子で開閉*/}
      {isShow && <Modal modalHandler={modalHandler} updateText={updateText} />}
    </div>
  );
};
export default Page;
/*--------------------------------------------------
モーダルコンポーネント
--------------------------------------------------*/
type Props = {
  modalHandler: () => void;
  updateText: (newText: string) => void;
};
export const Modal = ({ modalHandler, updateText }: Props) => {
  return (
    <>
      <button
        onClick={() => {
          modalHandler();
        }}
      >
        Close Modal
      </button>
      <input type="text" onChange={(event) => updateText(event.target.value)} />
    </>
  );
};

OK例

import React, { useState } from "react";
/*--------------------------------------------------
親コンポーネント
--------------------------------------------------*/
const Page = () => {
  const [isShow, setIsShow] = useState(false);
  const [text, setText] = useState("");
  const modalHandler = () => {
    setIsShow(!isShow);
  };
  const updateText = (newText: string) => {
    setText(newText);
  };
  let modalClass = "";
  if (isShow) {
    /*Tailwind CSS想定(display: hidden;と同等)*/
    modalClass = "hidden";
  } else {
    modalClass = "";
  }
  return (
    <div>
      <button
        onClick={() => {
          setIsShow(!isShow);
        }}
      ></button>
      {/*OK:CSSで開閉*/}
      <div className={`${modalClass}`}>
        <Modal
          modalHandler={modalHandler}
          updateText={updateText}
        />
      </div>
    </div>
  );
};
export default Page;
/*--------------------------------------------------
モーダルコンポーネント
--------------------------------------------------*/
type Props = {
  modalHandler: () => void;
  updateText: (newText: string) => void;
};
export const Modal = ({ modalHandler, updateText }: Props) => {
  return (
    <>
      <button
        onClick={() => {
          modalHandler();
        }}
      >
        Close Modal
      </button>
      <input type="text" onChange={(event) => updateText(event.target.value)} />
    </>
  );
};

letを使ってCSSの表示を切り替えているのですが、あまりスマートな感じがしませんね。よい方法を知ってましたらぜひ教えてください。こうした細かい箇所で悩んでいると開発が進まないですし、現状問題が起きそうでもない気がするのでこのまま進めていこうと思います。

まとめ

モーダルの開閉で変数が空になってしまいました。同じ原因でしたら開閉の仕組みを変えれば改善されるはずです。

ー この記事をシェアする? ー

  • 【React】三項演算子でモーダル開閉するとuseStateの値が空になる原因と対処法

この記事にコメントする

このサイトはreCAPTCHAとGoogleによって保護されています。プライバシーポリシー利用規約が適用されます。