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

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

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

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

React.js

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

Q&A

解決済

1回答

3400閲覧

【React.js】用意したすべてのフォームに有効な値が入力されたら、送信ボタンのdisabledを解除したい。

TofuLove

総合スコア14

JavaScript

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

React.js

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

0グッド

0クリップ

投稿2020/01/12 03:49

前提・実現したいこと

Reactで作成しているアプリにお問い合わせフォームを設けています。
下記がサンプルです。
サンプル

送信ボタンはデフォルトでdisabled状態です。
用意したすべてのフォームに有効な値が入力されたら、送信ボタンのdisabledを解除し、送信ボタンを押せるようにしたいです。

該当のソースコード

jsx

1import React, { useState } from "react"; 2 3export default function App() { 4 const [forms, setForms] = useState([false, false, false]); 5 console.log(forms); 6 7 const checkName = e => { 8 if (e.target.value === "") { 9 setForms((forms[0] = false)); 10 console.log(forms); 11 return; 12 } 13 setForms((forms[0] = true)); 14 console.log(forms); 15 }; 16 const checkMail = e => { 17 if (e.target.value === "") { 18 setForms((forms[1] = false)); 19 return; 20 } 21 setForms((forms[1] = true)); 22 }; 23 const checkMessage = e => { 24 if (e.target.value === "") { 25 setForms((forms[2] = false)); 26 return; 27 } 28 setForms((forms[2] = true)); 29 }; 30 31 const send = () => { 32 alert("送信しました。"); 33 }; 34 35 return ( 36 <form> 37 <p> 38 お名前 39 <input type="text" onChange={checkName} /> 40 </p> 41 <p> 42 メールアドレス 43 <input type="email" onChange={checkMail} /> 44 </p> 45 <p> 46 お問い合わせ内容 47 <input type="text" onChange={checkMessage} /> 48 </p> 49 <button onClick={send} disabled={forms !== [true, true, true]}> 50 送信 51 </button> 52 </form> 53 ); 54} 55

発生している問題

すべてのフォームに値を入力しても、送信ボタンのdisabledの解除ができていません。

送信ボタンの状態を下記のようにstateで管理しており、

jsx

1const [forms, setForms] = useState([false, false, false]);

formsが[true,true,true]になったら、送信ボタンのdisabledを解除するようにしています。

jsx

1<button onClick={send} disabled={forms !== [true, true, true]}>

setStateは各種フォームにonChangeイベントを用意し、「入力値があるか無いか」を条件に、booleanをforms配列に代入しています。

しかし、試しにお名前フォームに値を入力すると、

console

1[true, false, false] 2true

が一度にコンソールに表示されます。

console
※コンソールの一番上の[false,false,false]はAppコンポーネント描画時に表示されるものです。
以降のonChangeイベントによるコンソールの結果は、配列ではなくbooleanのみです。
また、メールとお問い合わせ内容フォームに入力時のコンソールの結果は、初回からbooleanのみです。


私の用意したサンプルはonChangeイベントのたびにsetStateにより再レンダリングされているので、パフォーマンス性的に良くないかと存じます。
よりパフォーマンス性に優れ、よりシンプルに実装できる方法がありましたら、ご教示いただけますと幸いです。
「実現したいこと」が実現できればよいので、最初に提示したサンプルの目指す実装方法にこだわるつもりはありません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

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

修正前

jsx

1<button onClick={send} disabled={forms !== [true, true, true]}>

修正後

jsx

1<button onClick={send} disabled={forms.some(ok => !ok)}>

追記

配列formsの先頭要素を false に変更するようにsetFormsしている行が、

修正前

javascript

1setForms((forms[0] = false));

となっていますが、これだと、setForms が実行された後の、次の forms の値が false になってしまい、配列にならなくなってしまい、そのために

"TypeError forms.some is not a function"というエラーメッセージが表示されました。

ということになります。setForms に与える引数は、3個のboolean値を要素とする配列を渡す必要があります。ですので、上記を以下のように修正します。

修正後

jsx

1setForms([ false, forms[1], forms[2] ]);

上記を含めて、setForms((forms[i] = true or false)); という書き方をしている行は、全部で6箇所ありますが、上記の他の5箇所についても(全く同じ、ではなく同様の修正をする必要があります。

投稿2020/01/12 04:23

編集2020/01/12 05:41
jun68ykt

総合スコア9058

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

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

TofuLove

2020/01/12 05:06

ご回答いただきありがとうございます。修正後コードをコピペしお名前フォームに値を入力したところ、"TypeError forms.some is not a function"というエラーメッセージが表示されました。修正後コードのみをコピペしたため、修正後コードを適用するにあたりほかに必要な修正箇所がありましたらご連絡いただけますと幸いです。
jun68ykt

2020/01/12 05:42

setForms している行が6箇所ありますが、それらを修正する必要があります。どのような修正をすればよいかを追記しました。参考になれば幸いです。
TofuLove

2020/01/12 06:23

おかげさまで実現したいことが実装できました!ありがとうございました。setStateについては配列そのものをセットする必要があったわけですね。また、array.some()については存じていなかったのですが、この機会に知ることができ大変勉強になりました。修正後コードで言えば配列にひとつでもfalseがあればtrueを返す(disabled=true;)ということでしょうか。重ねてにはなりますがありがとうございました。
jun68ykt

2020/01/12 06:31

どういたしまして。 > 配列にひとつでもfalseがあればtrueを返す はい。そのとおりです。 some と合わせて覚えておかれるとよいのは every です。以下、参考まで。 JavaScriptのsomeとeveryがすごく便利(@i_am_master_yodaさん) https://qiita.com/i_am_master_yoda/items/224ff73443b4566ec8e8 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/every https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問