質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

2回答

1145閲覧

Reactで関数が複数回呼ばれてしまう

minato2000

総合スコア10

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

1クリップ

投稿2023/02/03 01:52

編集2023/02/03 01:59

実現したいこと・前提

JSXが縦に長くなってしまうと見づらいので別けて書きたいです。
別けて書く為に関数化を試しました。
しかし、関数が複数回呼ばれてしまう問題が発生しました。

該当のソースコード

TypeScript

1import * as React from 'react'; 2import './style.css'; 3import 'bootstrap/dist/css/bootstrap.min.css'; 4 5import Button from 'react-bootstrap/Button'; 6import Modal from 'react-bootstrap/Modal'; 7 8export default function App() { 9 const [visible, setVisible] = React.useState(false); 10 const [text, setText] = React.useState('abc'); 11 12 const MyDialog = () => { 13 console.log('MyDialogが表示されました'); 14 15 return ( 16 <Modal show={visible} onHide={() => { setVisible(false); }}> 17 <Modal.Header closeButton> 18 <Modal.Title>タイトル</Modal.Title> 19 </Modal.Header> 20 21 <Modal.Body> 22 <input type="text" value={text} onChange={(e) => { setText(e.target.value); }} /> 23 </Modal.Body> 24 25 <Modal.Footer> 26 <Button variant="secondary">閉じる</Button> 27 <Button variant="primary">保存する</Button> 28 </Modal.Footer> 29 </Modal> 30 ); 31 }; 32 33 return ( 34 <div> 35 <MyDialog /> 36 37 <Button variant="primary" onClick={() => { setVisible(true); }}> 38 モーダルダイアログを表示する 39 </Button> 40 </div> 41 ); 42}

https://stackblitz.com/edit/react-ts-v6wluw?file=App.tsx

試したこと

関数化をやめて、関数内のコードをJSXにそのままコピペすると問題なく動作しました。
しかし、やりたい事としてはJSXを別けて書くことなので本末転倒です・・・。

補足情報(FW/ツールのバージョンなど)

  • "@popperjs/core": "^2.11.6",
  • "@types/react": "^18.0.8",
  • "@types/react-dom": "^18.0.2",
  • "bootstrap": "^5.2.3",
  • "react": "^18.1.0",
  • "react-bootstrap": "^2.7.0",
  • "react-dom": "^18.1.0"

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2023/02/03 02:21

関数コンポーネントの中で関数コンポーネントを定義するのは良くないような…。
guest

回答2

0

やりたいことはこういうイメージでいいんでしょうか?
(最終的にはMyDialogも別ファイルに移動させるとは思いますが)

関数が複数回呼ばれてしまう問題が発生しました。

この件について何も述べられていませんが、もしやconsole.logが2回呼ばれていることについてでしょうか?
だとするのであればReact18からの仕様です
https://github.com/reactwg/react-18/discussions/19

typescript:App.tsx

1import * as React from 'react'; 2import './style.css'; 3import 'bootstrap/dist/css/bootstrap.min.css'; 4 5import Button from 'react-bootstrap/Button'; 6import Modal from 'react-bootstrap/Modal'; 7 8const MyDialog = ({visible,setVisible,text,setText}) => { 9 console.log('MyDialogが表示されました'); 10 11 return ( 12 <Modal show={visible} onHide={() => { setVisible(false); }}> 13 <Modal.Header closeButton> 14 <Modal.Title>タイトル</Modal.Title> 15 </Modal.Header> 16 17 <Modal.Body> 18 <input type="text" value={text} onChange={(e) => { setText(e.target.value); }} /> 19 </Modal.Body> 20 21 <Modal.Footer> 22 <Button variant="secondary">閉じる</Button> 23 <Button variant="primary">保存する</Button> 24 </Modal.Footer> 25 </Modal> 26 ); 27}; 28 29export default function App() { 30 const [visible, setVisible] = React.useState(false); 31 const [text, setText] = React.useState('abc'); 32 33 return ( 34 <div> 35 <MyDialog visible={visible} setVisible={setVisible} text={text} setText={setText} /> 36 37 <Button variant="primary" onClick={() => { setVisible(true); }}> 38 モーダルダイアログを表示する 39 </Button> 40 </div> 41 ); 42}

投稿2023/02/03 09:20

sk-sora--ypi

総合スコア528

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

minato2000

2023/02/03 10:20 編集

ご回答ありがとうございます。 > やりたいことはこういうイメージでいいんでしょうか? はい。あっております。 関数で別けてみようと自分で考えていたのですが、うまく行かずに質問しました。 > もしやconsole.logが2回呼ばれていることについてでしょうか? はい。おっしゃる通りです。 初回に画面を表示した時に2回呼ばれます。 頂いたコードを実際に試してみました。 初回に画面を表示した時に1回呼ばれるようになりました。 こちらは解決しました。 しかし、ダイアログ内のテキストを変更するたびにconsole.logで「MyDialogが表示されました」が呼ばれるのですがこちらはどのように解決すればよいでしょうか? React18からの仕様であるStrictModeが原因という事なので、以下の通りStrictModeを消してみたのですがダメでした。 ```diff - <StrictMode> <App /> - </StrictMode> ```
maisumakun

2023/02/03 14:40 編集

> console.logで「MyDialogが表示されました」が呼ばれるのですがこちらはどのように解決すればよいでしょうか? 呼ばれてしかるべきものです。コンポーネントの引数を変えれば再描画が行われます。
minato2000

2023/02/03 15:07

そうなんですね。 1文字打つたびに入力のフォーカスが毎回外れてしまうので、1文字打つたびにマウスでフォームを選択しなければ入力できない状態になるのでフォームが含まれるJSXは分離できないということですね。ありがとうございました。
maisumakun

2023/02/05 10:50

> 1文字打つたびに入力のフォーカスが毎回外れてしまうので それで困っていたのであれば、質問時点で明記してください。 関数コンポーネントが呼ばれることは抑制できませんが、フォーカスが外れるような再描画については抑制できる可能性があります。
maisumakun

2023/02/05 10:55 編集

…というより、この回答のコードで「1文字打つたびに入力のフォーカスが毎回外れてしまう」という現象が再現しません。
guest

0

しかし、関数が複数回呼ばれてしまう問題が発生しました。

なぜそれが問題なのでしょうか。関数コンポーネントの呼ばれ方は保証されません

いつ何回呼ばれるかを担保したい処理は、useEffectなどを使って書いてください。

投稿2023/02/03 14:38

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問