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

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

新規登録して質問してみよう
ただいま回答率
85.46%
Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

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

Q&A

0回答

1958閲覧

ReactでDialogコンポーネントを再レンダリングせず非同期処理したい

Romay

総合スコア40

Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

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

0グッド

0クリップ

投稿2021/08/07 11:40

編集2021/08/11 15:12

前提・実現したいこと

Ruby on Rails×ReactでWebアプリケーションを作成しています。
元々Reactでコンポーネントを細かく分けずに実装していたのですが、見通しをよくするため適切に分けようとしていたところ、意図しない動きになったため質問させていただきます。

ECサイトのようなWebアプリケーションで、商品の一覧と商品の詳細ダイアログが表示され、ダイアログ上で個数を変更できるようにしていますが、コンポーネントを分けたところ、個数を変更するたびにダイアログが再レンダリングされてしまい、UXとして良くない状態になってしまいました。

利用技術

  • Ruby on Rails
  • React
  • Material-UI
  • TypeScript

コード比較

元々のコード(意図する動きを実現)

index.jsx

React

1const UserManagementsMenu: React.FC<Props> = (props: Props) => { 2 const classes = useStyles() 3 4 5 const handleItemCount = (counter: boolean) => { 6 const newCount = 0 7 if (counter == true) { 8 setItemCount(itemCount + 1) 9 setSwitchDeleteButton(true) 10 } else { 11 if (itemCount > 2) { 12 setItemCount(itemCount - 1) 13 } else { 14 if (itemCount == 2) { 15 setItemCount(itemCount - 1) 16 } 17 setSwitchDeleteButton(false) 18 } 19 } 20 } 21 22return ( 23 <ThemeTemplate> 24 <Container> 25 //商品一覧のコードベタがき (省略) 26 27 //商品の詳細のDialogベタがき (簡素化しています) 28 <Dialog> 29 <DialogContent> 30 <Card> 31 <CardContent> 32 </CardContent> 33 <CardActions> 34 <Grid container spacing={3}> 35 <Grid item xs={3}> 36 <div > 37 <IconButton 38 onClick={() => handleItemCount(false)}> 39 </IconButton> 40 </div> 41 </Grid> 42 <Grid item xs={3}> 43 <div> 44 <Button aria-label="previous"> 45 <Typography> 46 {itemCount} 47 </Typography> 48 </Button> 49 </div> 50 </Grid> 51 <Grid item xs={3}> 52 <div className={classes.controls}> 53 <IconButton onClick={() => handleItemCount(true)}> 54 </IconButton> 55 </div> 56 </Grid> 57 </Grid> 58 </CardActions> 59 </Card> 60 </DialogContent> 61 </dialog> 62 </Container> 63 </ThemeTemplate> 64

コンポーネントを分けたコード(意図しない動きになった)

index.jsx

React

1//import系を全てここに記載 2import * as React from "react" 3import {useState, useEffect, createRef} from "react" 4省略 5 6 7//Propsをここに全て記載 8type Props = { 9 shop: { 10 id: number 11 name: string 12 } 13 省略 14 } 15 16 17//CSS系はここに記載 18const useStyles = makeStyles((theme: Theme) => 19 createStyles({ 20 root: { 21 padding: theme.spacing(1, 2, 1), 22 margin: theme.spacing(7, 0, 5), 23 }, 24 省略 25 }) 26 ) 27 28 29 30//以下 UserManagementsMenuの中身, このViewの主な要素はこの中に記載 31const UserManagementsMenu: React.FC<Props> = (props: Props) => { 32 const classes = useStyles() 33 34 //hooks系もここに全て記載 35   const [name, setName] = useState(String) 36   const [openItemDialog, setOpenItemDialog] = useState(false) 37 省略 38   39 40 41 const handleItemCount = (counter: boolean) => { 42 const newCount = 0 43 if (counter == true) { 44 setItemCount(itemCount + 1) 45 setSwitchDeleteButton(true) 46 } else { 47 if (itemCount > 2) { 48 setItemCount(itemCount - 1) 49 } else { 50 if (itemCount == 2) { 51 setItemCount(itemCount - 1) 52 } 53 setSwitchDeleteButton(false) 54 } 55 } 56 } 57 58//他handlerも同様に記載、これらは変更していない 59 60 61 62//以下、複数の分けたコンポーネントをここに記載, 全てUserManagementsMenuの中に存在 63//変更している箇所はここのみ 64 const ItemList =() => { 65 const classes = useStyles() 66 return ( 67               省略 68 ) 69 } 70 71 72 const ItemDetailDialog =() => { 73 const classes = useStyles() 74 return ( 75 <> 76 <Dialog> 77 <DialogContent> 78 <Card> 79 <CardContent> 80 </CardContent> 81 <CardActions> 82 <Grid container spacing={3}> 83 <Grid item xs={3}> 84 <div > 85 <IconButton onClick={() => handleItemCount(false)}> 86 </IconButton> 87 </div> 88 </Grid> 89 <Grid item xs={3}> 90 <div> 91 <Button aria-label="previous"> 92 <Typography> 93 {itemCount} 94 </Typography> 95 </Button> 96 </div> 97 </Grid> 98 <Grid item xs={3}> 99 <div className={classes.controls}> 100 <IconButton onClick={() => handleItemCount(true)}> 101 </IconButton> 102 </div> 103 </Grid> 104 </Grid> 105 </CardActions> 106 </Card> 107 </DialogContent> 108 </dialog> 109 </> 110 ) 111 } 112 113 114 115//ここでそれぞれのコンポーネントを呼び出している 116 return ( 117 <ThemeTemplate> 118 <Container> 119 <ItemList/> 120 <ItemDetailDialog/> 121 </Container> 122 </ThemeTemplate> 123 ) 124} 125 126//ここまでがUserManagementsShopMenu: React.FC<Props> の中身 127 128export default UserManagementsMenu 129//ここで終わり

発生している問題

onClickイベントが発生した際に、ItemDetailDialogコンポーネントが再レンダリングされてしまいます。元々のコードでは、再レンダリングされず、onclickで個数を変更した時は、Dialogはそのままで個数の表示だけ変えることができました。
コンポーネントは、分けても同じ1ファイルに記述しています。
コンポーネントを分けた以外には何も追加したり消したりしていません。

試したこと

Reactの基本的なところかと思うのですが、これまでちゃんとコンポーネントを分けて開発していなかったため、この事象を解決できずにいます。。お教えいただけますと嬉しいです。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

anozon

2021/08/07 15:50

しっかり function ComponentA() {} function ComponentB() {} というふうに分けていますか? 関数内に分けていませんか?
FKM

2021/08/08 01:02

コンポーネントの中にイベント置くと置いた回数分制御されたりしますが、それと関係あるんでしょうかね。
Romay

2021/08/08 02:39

anozonさん コメントありがとうございます。 const ItemDetailDialog=()=>{ const classes=useStyles() return ( )} としているのは、しっかり分けられていないのでしょうか? 記述場所としては、 const UserManagementsMenu: React.FC<Props> = (props: Props) の中に書いているのですが、この外に書く必要があるのでしょうか? どこまでが"関数内"なのかいまいち分かっておらず。。。
Romay

2021/08/08 02:40

FKMさん コメントありがとうございます。 onclickイベントの発生回数分制御されているようなので、関係あるのかもしれないです。
anozon

2021/08/08 04:26

必要な情報は props で渡すようして、分けてみてください。
p19ljk

2021/08/10 02:38

インデントがずれているので、どこまでかどのブロックなのかが分かりづらいですね。 最後のreturnもどのブロックにも属さずいきなり登場していますし。 もう一度正確なコードを記述してみてください。
Romay

2021/08/11 15:13

anozonさん, p19ljkさん ありがとうございます。インデントのズレを直し、どこまでがどのブロックかわかるようにコメントも入れました。ご確認頂けますと幸いです。
p19ljk

2021/08/12 00:42

そもそもUserManagementsMenuコンポーネント内でItemDetailDialogを生成している時点でコンポーネントを分けたとは言わないのでは? ちゃんと親コンポーネントの外へ記述しましょう。 (それだけで解決するわけではないですが。。。)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

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

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

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問