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

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

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

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

JavaScript

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

React.js

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

Q&A

解決済

1回答

1674閲覧

React-Redux 複雑なネスト構造の一部だけを更新したいのですが、できないのでどなたか助けてください...

itow39

総合スコア1

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

JavaScript

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

React.js

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

0グッド

0クリップ

投稿2021/08/31 17:25

実現したいこと

React-Reduxのreducerで以下の要素の一部だけを更新しようとしています。

const initialState = { "TaskLogs" : [ { "CreatedDate" : "2020/81", "TaskGroupName": "SAMPLE_TITLE", "Tasks": [ { "Task": "FirstTask", "Date": { "8/1": "11", "8/2": "", "8/3": "", "8/4": "", "8/5": "", "8/6": "", "8/7": "", "8/8": "", "8/9": "", "8/10": "", "8/11": "", "8/12": "", "8/14": "" } }, { "Task": "SecondTask", "Date": { "8/1": "2", "8/2": "", "8/3": "", "8/4": "", //例えば、ここの値だけを変更させたい "8/5": "", "8/6": "", "8/7": "", "8/8": "", "8/9": "", "8/10": "", "8/11": "", "8/12": "", "8/14": "" } }, { "Task": "ThirdTask", "Date": { "8/1": "300", "8/2": "", "8/3": "", "8/4": "", "8/5": "", "8/6": "", "8/7": "", "8/8": "", "8/9": "", "8/10": "", "8/11": "", "8/12": "", "8/14": "" } } ] }, ] } const reducer = (state = initialState, action) =>{ switch(action.type) { case ADD_TASKLOG:{ return { ...state, TaskLogs :[...state.TaskLogs, action.TaskLog] } } case UPDATE_TASKLOG:{ //TaskLogs[i].Tasks[j].Date[k] //更新先 let i = action.data[0] //TaskLogs(配列)を指定する数値 let j = action.data[1] //Tasks(配列)を指定する数値 let k = action.data[2] //Date(オブジェクト)を指定するプロパティ名(例:k = "8/6") let value = action.data[3] //更新させたい値 (例:value="あああ", Date{"8/6": "あああ"}) return { ...state, TaskLogs: ??????←どんな処理を書けばよいのかわからない。 } } case UPDATE_TASKGROUPNAME:{ //省略 } case DELETE_TASKLOG:{ // 省略 } default:{ return state } } }

試したこと

更新先めがけて、ネストされたオブジェクトを以下のように一段一段と降りるように設定しました。
しかし、無事更新されるもののTaskLogsが配列からオブジェクトに変換されてしまったので結果的にダメでした。

   case UPDATE_TASKLOG:{ //TaskLogs[i].Tasks[j].Date[k] //更新先 let i = action.data[0] //TaskLogs(配列)を指定する数値 let j = action.data[1] //Tasks(配列)を指定する数値 let k = action.data[2] //Date(オブジェクト)を指定するプロパティ名(例:k = "8/6") let value = action.data[3] //更新させたい値 (例:value="あああ", Date{"8/6": "あああ"}) return { ...state, TaskLogs:{ //試したところ ...state.TaskLogs, [i]:{ ...state.TaskLogs[i], Tasks:{ ...state.TaskLogs[i].Tasks, [j]: { ...state.TaskLogs[i].Tasks[j], Date:{ ...state.TaskLogs[i].Tasks[j].Date, [k]:[value] } } } } } } }

ほかにも以下のようなサイトで試してみましたが、どれも私ほどのひどいネスト構造ではなく、シンプルなもののため参考になりませんでした。
応用できない実力不足を恨みたいところですが、それは回答者様に期待しようと思います。よろしくお願いいたします。
https://www.py4u.net/discuss/283462
https://qiita.com/kuropp/items/f295c45e1705677a7a48

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

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

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

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

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

guest

回答1

0

ベストアンサー

いっぺんに作ろうとすると辛くなってくるので、深いところから順々に作っていき、段階ごとに一時的な変数に入れていけば確実やと思うで。こないな感じですわ。

javascript

1const nextDate = { 2 ...state.TaskLogs[i].Tasks[j].Date, 3 [k]: value, 4}; 5 6const nextTasks = state.TaskLogs[i].Tasks.map((e, index) => ({ 7 ...e, 8 Date: index === j ? nextDate : e.Date, 9})); 10 11const nextTaskLogs = state.TaskLogs.map((e, index) => ({ 12 ...e, 13 Tasks: index === i ? nextTasks : e.Tasks, 14})); 15 16return { TaskLogs: nextTaskLogs };

補足:

本題とは関係あらへんのやけど、ちょっとお節介させてもらいますねん。以下の4行

javascript

1let i = action.data[0]; //TaskLogs(配列)を指定する数値 2let j = action.data[1]; //Tasks(配列)を指定する数値 3let k = action.data[2]; //Date(オブジェクト)を指定するプロパティ名(例:k = "8/6") 4let value = action.data[3]; //更新させたい値 (例:value="あああ", Date{"8/6": "あああ"})

やけど、(1)分割代入を使う。(2) なるべくletではなくconstを使う。という2点でリファクタすると、こないな感じ:

javascript

1const [i, j, k, value] = action.data;

で一行で書けるよって。

もうひとつ補足:

すでにベストアンサーにしてもろうた後やけど、もう一個お節介するわな。これだけネストの深いstateだと、immutable-js を使うのもありかもしれへんよ。以下は、具体的には、こんな感じになるでしょうというイメージです。

  • yarn add immutable して
  • initialState を定義しているところで、

javascript

1import { Map as ImmutableMap } from 'immutable'

としておきます。ImmutableMap という別名でインポートするのは、念のため標準のMapと区別するためですわ。

  • ほんで、initialStateを以下のように、immutable-js のMapで作るんや。

javascript

1 const initialState = ImmutableMap({ 2 TaskLogs : [ 3 { 4 CreatedDate : "2020/81", 5 TaskGroupName: "SAMPLE_TITLE", 6 Tasks: [ 7 { 8 Task: "FirstTask", 9 Date: { 10 "8/1": "11", 11 "8/2": "", 12 "8/3": "", 13 "8/4": "", 14 "8/5": "", 15 "8/6": "", 16 "8/7": "", 17 "8/8": "", 18 "8/9": "", 19 "8/10": "", 20 "8/11": "", 21 "8/12": "", 22 "8/14": "" 23 } 24 }, 25 { 26 Task: "SecondTask", 27 Date: { 28 "8/1": "2", 29 "8/2": "", 30 "8/3": "", 31 "8/4": "", //例えば、ここの値だけを変更させたい 32 "8/5": "", 33 "8/6": "", 34 "8/7": "", 35 "8/8": "", 36 "8/9": "", 37 "8/10": "", 38 "8/11": "", 39 "8/12": "", 40 "8/14": "" 41 } 42 }, 43 { 44 Task: "ThirdTask", 45 Date: { 46 "8/1": "300", 47 "8/2": "", 48 "8/3": "", 49 "8/4": "", 50 "8/5": "", 51 "8/6": "", 52 "8/7": "", 53 "8/8": "", 54 "8/9": "", 55 "8/10": "", 56 "8/11": "", 57 "8/12": "", 58 "8/14": "" 59 } 60 } 61 ] 62 }, 63 ] 64 });

こうやって、state全体をプレーンオブジェクトではなく、immutable-jsのマップにしておくと、case UPDATE_TASKLOG:んとこは、こないな感じ

javascript

1case UPDATE_TASKLOG: { 2 const [i, j, k, value] = action.data; 3 return state.setIn( ['TaskLogs', i, 'Tasks', j, 'Date', k], value); 4}

にかなり簡単に書けると思います。ただこうすると、どのcaseでもstateをimmutable-jsのマップに変更したことでの修正をせなあきまへん。immutable-jsに慣れるための学習コストがそれなりにかかりますやろな。参考までに、 Redux のstateに immutable.jsを使うサンプルの記事ですねん。➡ Redux stateにimmutable.jsを使う

投稿2021/08/31 20:08

編集2021/09/01 03:47
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

itow39

2021/09/01 03:44

ご回答ありがとうございます。本題のコードもsuwmnさんのおかげで無事動きました。あと補足情報のリファクタリングも勉強になりました。助けてもらって勉強もできたので一石二鳥です。本当ありがとうございました!!
退会済みユーザー

退会済みユーザー

2021/09/01 03:48

おおきに〜。お節介ついでに、「もうひとつ補足」を回答に書いたよって、参考にしたってや〜
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問