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

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

新規登録して質問してみよう
ただいま回答率
85.47%
React.js

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

Q&A

1回答

99閲覧

【React】配列内の特定のオブジェクト内の配列に値を追加したい

_chii

総合スコア50

React.js

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

0グッド

0クリップ

投稿2024/04/20 17:21

実現したいこと

現在、2階層の ToDo アプリを作成しているのですが、2階層目の新しい要素を追加する処理のロジックがうまく実装できません。
どのように論理立てて実装するかがわかっていない段階です。

発生している問題・分からないこと

具体的な処理の流れを理解できていません。
下記に現状の簡易的な処理を書きます。

下記のソースコードが今回のはまっている問題の処理を簡略化したものなのですが、Child.jsxのinputに値を入力したときにlistsの特定のオブジェクトのsubListsに追加したいのですが、その処理について理解できません。

例えばuseStateでsubListsは定義していませんが、これはChild.jsx内で定義する必要があるのでしょうか?それともinputの値を親に渡して親に関数処理を記述するべきでしょうか?

ただ仮にそれを言語化できたとしても、実装のロジックを組み立てることができるのかもわかりません。

該当のソースコード

Parent.jsx

1const listsDefault = [ 2 { 3 title: 'タイトル1', 4 isCompleted: false, 5 subLists: [ 6 { 7 item: 'タイトル1 のアイテム1', 8 isCompleted: false, 9 }, 10 { 11 item: 'タイトル1 のアイテム2', 12 isCompleted: false, 13 }, 14 ], 15 }, 16 { 17 title: 'タイトル2', 18 isCompleted: false, 19 subLists: [ 20 { 21 item: 'タイトル2 のアイテム1', 22 isCompleted: false, 23 }, 24 { 25 item: 'タイトル2 のアイテム2', 26 isCompleted: false, 27 }, 28 ], 29 }, 30]; 31 32const Parent = () => { 33 const [lists, setLists] = useState(listsDefault); 34 35// ここに関数が書いてありますが省略しています 36 37 return ( 38 39 // 1階層目のリストや特定のリストをクリックすることで2階層目の特定のリストが表示されるコンポーネントが書かれていますが、今回は省略します 40 41  // listNum は関数処理は省略していますが、1階層目の特定のリストをクリックすることで変化する数値の値です。 42 <SubLists lists={lists} listNum={listNum} /> します 43 ); 44 45}; 46 47export default Parent; 48

Child.jsx

1const SubLists = ({ lists, listNum }) => { 2 return ( 3 <> 4 <main > 5 <form> 6 <input placeholder="タスクを入力..." /> 7 </form> 8 <ul> 9 // 2階層目のToDoがリストで表示されます 10 {lists[listNum].subLists.map((list, index) => ( 11 <li key={index}> 12 <span>{list.item}</span> 13 </li> 14 ))} 15 </ul> 16 </main> 17 </> 18 ); 19}; 20 21export default SubLists;

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

様々な情報やデバックなどを試みてみたのですが、理解できませんでした。

補足

特になし

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

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

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

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

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

guest

回答1

0

複雑なステートを取り扱う必要があるので TypeScript の型注釈を勝手に使用して、コードの意味が不明瞭になるような一部の変数・プロパティ名を勝手に書き換え等していますが…

このように、SubTasks コンポーネントに、コールバック形式の onAddSubTask Prop を追加して、form の onSubmit のイベントハンドラ中でこのコールバック関数を呼び出して、そのときに input から抽出した値を渡してあげることによって実現できます。

tsx

1import { type FC } from "react"; 2import { SubTaskDetail, type TaskDetail } from "./taskdetail"; 3 4type Props = { 5 task: TaskDetail; 6 onAddSubTask: (task: SubTaskDetail) => void; 7}; 8 9export const SubTasks: FC<Props> = ({ task, onAddSubTask }) => { 10 return ( 11 <div> 12 <form 13 onSubmit={(e) => { 14 e.preventDefault(); 15 const formData = new FormData(e.currentTarget); 16 const title = formData.get("title"); 17 if (typeof title !== "string") return; 18 if (title === "") return; 19 onAddSubTask({ item: title, isCompleted: false }); 20 }} 21 > 22 <input name="title" placeholder="タスクを入力" /> 23 </form> 24 25 {task.subTasks.map(/*省略*/)} 26 </div> 27 ); 28}; 29 30

TaskDetail と SubTaskDetail の型定義

ts

1export type TaskDetail = { 2 title: string; 3 isCompleted: boolean; 4 subTasks: SubTaskDetail[]; 5}; 6 7export type SubTaskDetail = { item: string; isCompleted: boolean };

親コンポーネント

tsx

1 2import { useState } from "react"; 3import { type TaskDetail, type SubTaskDetail } from "./taskdetail"; 4import { SubTasks } from "./sub-lists"; 5 6export const taskListDefaultValue: TaskDetail[] = /* 省略 */; 7 8const Parent = () => { 9 const [tasks, setTasks] = useState<TaskDetail[]>(taskListDefaultValue); 10 const [index, setIndex] = useState<number>(0); 11 12 const handleAddSubListItem = (itemDetail: SubTaskDetail) => { 13 return setTasks( 14 tasks.map((value, i) => { 15 if (i !== index) return value; 16 // listNum 番目の要素のみ、以下の処理で subLists に追加する 17 const { subTasks } = value; 18 return { 19 ...value, 20 subTasks: [...subTasks, itemDetail], 21 }; 22 }) 23 ); 24 }; 25 26 return ( 27 <div> 28 <SubTasks task={tasks[index]} onAddSubTask={handleAddSubListItem} /> 29 </div> 30 </div> 31 ); 32}; 33 34export default Parent; 35

手前味噌ですが、このような配列状のステートが絡むような UI の状態を親子コンポーネント間でどのように役割分担すべきかのアイデアを書きとめた記事があります https://qiita.com/honey32/items/2e6206c7dc1974b9bf9a

onSubmit の中の書き方の参考記事: https://qiita.com/nuko-suke/items/1393995fd53ecaeb1cbc

投稿2024/04/21 09:45

編集2024/04/21 09:47
honey32

総合スコア175

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問