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

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

新規登録して質問してみよう
ただいま回答率
85.35%
オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

JavaScript

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

React.js

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

Q&A

解決済

2回答

2128閲覧

増減する複数のinputの値からオブジェクトの配列を生成したいです。

evgenia

総合スコア28

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

JavaScript

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

React.js

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

2グッド

0クリップ

投稿2021/08/09 02:10

編集2021/08/09 07:16

質問解決後の追記

suwmn50799さんのご回答にベストアンサーを付けていますが、実質的ベストアンサーはmaisumakunさんのご回答のコメント欄にある、suwmn50799さんの実装例です。
ただし、maisumakunさんにベストアンサーを付けると、suwmn50799さんのteratailのスコアに影響が無いため、suwmn50799さんのご回答にベストアンサーを付けております。

前提

CodeSandBox
上記はデモです。

ユーザーの情報を入力するコンポーネントがあります。
入力欄は最大10まで増やせます。
また、任意の入力欄を削除できます。

実現したいこと

Submitボタンを押した際、No.ごとのname、age、addressそれぞれの値でオブジェクトを生成し、生成したオブジェクトを配列に格納したいです。

例えば、下記のようなオブジェクトの配列を作成したいです。

[ {name: "Suzuki", age: 20, address: "Tokyo"}, {name: "Sato", age: 30, address: "Osaka"}, {name: "Tanaka", age: 40, address: "Fukuoka"} ]

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

No.ごとの各inputの値を取得できていません。

該当のソースコード

javascript

1import { useState, useRef } from "react"; 2 3const getUniqueStr = () => { 4 return ( 5 new Date().getTime().toString(16) + 6 Math.floor(1000 * Math.random()).toString(16) 7 ); 8}; 9 10export default function App() { 11 const defaultUser = () => { 12 return { 13 id: getUniqueStr(), 14 name: "", 15 age: 0, 16 address: "" 17 }; 18 }; 19 const [users, setUsers] = useState([defaultUser()]); 20 21 const addItem = (e) => { 22 e.preventDefault(); 23 if (users.length < 10) setUsers([...users, defaultUser()]); 24 }; 25 26 const deleteItem = (e) => { 27 e.preventDefault(); 28 const itemId = e.currentTarget.id; 29 const newItems = users.filter((user) => user.id !== itemId); 30 setUsers(newItems); 31 }; 32 33 const list = users.map((user, index) => ( 34 <tr key={user.id} id={`user${index}`}> 35 <td>{index + 1}</td> 36 <td> 37 <input type="text" name="name" /> 38 </td> 39 <td> 40 <input type="number" name="age" /> 41 </td> 42 <td> 43 <input type="text" name="address" /> 44 </td> 45 <td> 46 <button onClick={deleteItem} id={user.id}> 47 Delete 48 </button> 49 </td> 50 </tr> 51 )); 52 53 const formRef = useRef(null); 54 const submitData = (e) => { 55 e.preventDefault(); 56 const formCurrent = formRef.current; 57 console.log(formCurrent); 58 }; 59 60 return ( 61 <form onSubmit={submitData} ref={formRef}> 62 <button onClick={addItem}>Add</button> 63 <button type="submit">Submit</button> 64 <table> 65 <thead> 66 <tr> 67 <th>No.</th> 68 <th>Name</th> 69 <th>Age</th> 70 <th>Address</th> 71 <th>Delete</th> 72 </tr> 73 </thead> 74 <tbody>{list}</tbody> 75 </table> 76 </form> 77 ); 78}

試したこと

上記コードに含めていますが、useRefを使ってtrごとのDOMを取得して、tr以下のinputの値を取得する、という処理を試みました。

javascript

1const submitData = (e) => { 2 e.preventDefault(); 3 const formCurrent = formRef.current; 4 const userData = formCurrent.user0; 5 console.log(userData); 6 ... 7};

userDataはundefindでした。
useRefでname属性なら取得できることは確認できたのですが、trにname属性を付けるとlintに怒られました。


次に下記のように、input要素のname属性から値を取得してみました。

javascript

1const submitData = (e) => { 2 e.preventDefault(); 3 const formCurrent = formRef.current; 4 const inputNames = Array.from(formCurrent.name); 5 const names = inputNames.map(elm => elm.value); 6 console.log(names); 7 ... 8};

これで下記のようにNo.ごとではなくnameごとに値を取得することができました。

[ {"Suzuki"}, {"Sato"}, {"Tanaka"}, ]

同じ要領でageとaddressも配列を作れそうではあります。

しかし、複数の配列からオブジェクトを生成して配列に格納する方法が分かりませんでした。
「javascript 配列 統合」「javascript 配列 合成」などで検索すると、単一の配列にする方法なら分かりました。
Array.prototype.concat() - JavaScript | MDN


また、各inputの値をstateで管理すれば、値を取得できそうではありますが、パフォーマンス的によくないと考えられるため、stateで値を取得する方法はできるだけ避けたいです。

whoiwhoi, TofuLove👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

(都合により削除)
イメージ説明

投稿2021/08/09 04:45

編集2021/10/08 21:26
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2021/10/08 21:26 編集

(都合により削除)
evgenia

2021/08/09 07:05 編集

私の実現したいことができているコードを確認できました。ありがとうございます。とても簡略的なコードでした。 jQueryをほぼ触ったことない身からすると、なんでもかんでもstateを使ってしまっているため、今回の要件のようにリアルタイムでバリデーションを必要としない場合は、stateを利用せずに実装する方がパフォーマンス的にもコード量的にも無駄が少ないと考えていました。 loadshは調べてみたら脱loadshを目指す記事が2、3見つかったので、maisumakunさんからstateを利用した実装方法を24時間以内にご回答いただけなかった場合は、suwmn50799さんのご回答をベストアンサーにいたします。
guest

0

また、各inputの値をstateで管理すれば、値を取得できそうではありますが、パフォーマンス的によくないと考えられるため、stateで値を取得する方法はできるだけ避けたいです。

いえ、それがReact本来のやり方です。「パフォーマンス的によくない」というのは、どこからの情報でしょうか?

投稿2021/08/09 02:15

maisumakun

総合スコア146018

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

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

evgenia

2021/08/09 03:27 編集

どこからの情報ではありません。質問文にある通り私の考えです。お手数ですが、仰せの「React本来のやり方」を用いたコードを「回答」にご教示いただけますでしょうか。stateで管理する方法だとonChangeのたびにsetStateをする方法しか思いつかず、文字入力の度にinput要素をレンダリングするのは無駄が多くなり、パフォーマンス的にによくなさそうだなと思った次第です。
maisumakun

2021/08/09 03:28 編集

> stateで管理する方法だとonChangeのたびにsetStateをする方法しか思いつかず そのとおりで問題ありません。 > 文字入力の度にinput要素をレンダリングするのは無駄が多くなり、パフォーマンス的にによくなさそうだな それで十分実用になるからReactが成立しています。
evgenia

2021/08/09 06:53

onChangeでsetStateでも十分実用になることをご教示いただきありがとうございます。 そうしましたら、レンダリング回数が増えることはひとまず置いておき、stateを利用する方法をとろうと思います。 つきましては、度々のお願いで恐れ入りますが、stateを利用した実装方法をご教示いただけますでしょうか。
退会済みユーザー

退会済みユーザー

2021/08/09 06:59

横からえらいすんません > 仰せの「React本来のやり方」を用いたコード やねんけど、なんやろ、ざっくりこんなんになる思うで? https://codesandbox.io/s/amazing-curie-jlst7
evgenia

2021/08/09 07:12

> suwmn50799さん state利用版のデモもご用意いただきありがとうございます。 state利用でも十分シンプルなコードになっているので、state利用版コードを採用します。 重ねてありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問