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

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

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

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

React.js

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

Q&A

解決済

2回答

1578閲覧

[React]stateを変更しても表示が更新されない

aiai8976

総合スコア112

Material-UI

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

React.js

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

0グッド

0クリップ

投稿2020/06/07 13:07

前提・実現したいこと

Reactのstate管理についてですが、jsonを書き換えてsetした値が更新されているにもかかわらず再描画されません。値の表示は変更前のままになっています。
何か改善策はあるでしょうか。

発生している問題・エラーメッセージ

state変更後、再描画されない

該当のソースコード

const [selectedTime, setSelectedTime] = React.useState({ "1": { start: new Date(), end: new Date(), }, "2": { start: new Date(), end: new Date(), }, "3": { start: new Date(), end: new Date(), }, }); return( ... {Object.keys(selectedTime).map((key) => { let obj = selectedTime; const handleStartTimeChange = (date) => { obj[key].start = date; setSelectedTime(obj); console.log(selectedTime); //selectedTimeの値が更新されていることは確認 }; const handleEndTimeChange = (date) => { obj[key].end = date; setSelectedTime(obj); }; return ( <MuiPickersUtilsProvider utils={DateFnsUtils}> <Grid container justify="space-around"> <KeyboardTimePicker margin="normal" id="start" label="Start Time" value={selectedTime[key].start} onChange={handleStartTimeChange} KeyboardButtonProps={{ "aria-label": "change time", }} /> <KeyboardTimePicker margin="normal" id="end" label="End Time" value={selectedTime[key].end} onChange={handleEndTimeChange} KeyboardButtonProps={{ "aria-label": "change time", }} /> </Grid> </MuiPickersUtilsProvider> ); })}

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

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

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

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

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

guest

回答2

0

ベストアンサー

こんにちは。
handleStartTimeChange の以下の2行

修正前:

javascript

1obj[key].start = date; 2setSelectedTime(obj);

を、以下のように修正してみると、いかがでしょうか?

修正後:

javascript

1setSelectedTime({ ...obj, [key]: { ...obj[key], start: date } });

handleEndTimeChange のほうも同様です。

追記

リファクタリング案を挙げておきます。map の中で、各 dateの変更ハンドラーを作るのではなく、ひとつの変更ハンドラですべてをまかなうこともできるかなと思います。以下のような感じです。(※動作確認はしていません)

jsx

1const SomeComponent = props => { 2 const [selectedTime, setSelectedTime] = React.useState({ 3 "1": { 4 start: new Date(), 5 end: new Date() 6 }, 7 "2": { 8 start: new Date(), 9 end: new Date() 10 }, 11 "3": { 12 start: new Date(), 13 end: new Date() 14 } 15 }); 16 17 const handleTimeChange = (key, name, date) => { 18 setSelectedTime({ ...selectedTime, [key]: { ...selectedTime[key], [name]: date } }); 19 }; 20 21 return ( 22 <div> 23 {Object.entries(selectedTime).map(([key, { start, end }]) => ( 24 <MuiPickersUtilsProvider utils={DateFnsUtils} key={`picker-${key}`}> 25 <Grid container justify="space-around"> 26 <KeyboardTimePicker 27 margin="normal" 28 id="start" 29 label="Start Time" 30 value={start} 31 onChange={date => handleTimeChange(key, "start", date)} 32 KeyboardButtonProps={{ 33 "aria-label": "change time" 34 }} 35 /> 36 <KeyboardTimePicker 37 margin="normal" 38 id="end" 39 label="End Time" 40 value={end} 41 onChange={date => handleTimeChange(key, "end", date)} 42 KeyboardButtonProps={{ 43 "aria-label": "change time" 44 }} 45 /> 46 </Grid> 47 </MuiPickersUtilsProvider> 48 ))} 49 </div> 50 ); 51};

投稿2020/06/07 13:34

編集2020/06/07 22:45
jun68ykt

総合スコア9058

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

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

aiai8976

2020/06/07 13:40

いけました!ありがとうございます。 スプレッド構文について勉強します。
jun68ykt

2020/06/07 14:02

どういたしまして???? > いけました! とのことでよかったです。 > スプレッド構文について勉強します。 はい。新しいstate を作るとき、スプレッド構文はよく使います。 それと、map の中で、各dateを変えるときのハンドラーを個別に作るのではなく、mapの外にひとつ作っておいて、これを 1〜3 の、start および end の両方の場合の changeハンドラにするようにもできると思いますので、追記しておきました。 参考になれば幸いです。
aiai8976

2020/06/09 01:52

リファクタリング案に変更したところうまくいけました。 冗長だとわかっていたのですが、書き方がわからず放置していました。 entriesを使えばいいんですね。 大変勉強になりました。 ご丁寧にありがとうございました。 また、機会があればよろしくお願いします。
jun68ykt

2020/06/09 07:26

どういたしまして。丁寧なご返信ありがとうございます。 Object.entries もそうですが、リファクタしたほうの setSelectedTime({ ...obj, [key]: { ...obj[key], start: date } }); で使っているスプレッド構文と、[key]: { で使っている、Computed property names の合わせ技など、ES2015以降に追加された新しいメソッドや構文が、白紙からコードを書く時点で、スラスラ出てくるようになると、Reactのコードを楽に速く、かつ、初めから正解に近いコードを書けるようになります。いろんな人から、これはイイと思った技を盗んで、ご自身のものにしていけばよいかと思います。
guest

0

obj[key].start = date;のように、stateとして管理されているオブジェクトを破壊的に変更するのは適切ではありません。

コピーして変更を行ってから、変更後の新しいオブジェクトsetStateしてください。

投稿2020/06/07 13:24

maisumakun

総合スコア145184

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問