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

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

ただいまの
回答率

87.58%

【node.js】forEachで回した要素から、それぞれのformで値を送信したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 712

score 19

forEachで回した、それぞれのformから値を送信したい

node.jsを使って、簡単なsnsのwebアプリを開発しています。
「いいね」機能を実装中に以下のエラーメッセージが発生しました。

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

TypeError: C:\xampp\htdocs\sns_app\views\main.ejs:26
    24|             <a href="/new_tweet">新規追加</a>
    25|             <ul>
 >> 26|               <% tweets.forEach((tweet) => { %>
    27|                 <li class="tweet">
    28|                   <span class="tweet_id"><%= tweet.id %></span>
    29|                   <span class="tweet_content"><%= tweet.content %></span>

Cannot read property 'forEach' of undefined
    at eval (C:\xampp\htdocs\sns_app\views\main.ejs:15:15)
    at main (C:\xampp\htdocs\sns_app\node_modules\ejs\lib\ejs.js:691:17)
    at tryHandleCache (C:\xampp\htdocs\sns_app\node_modules\ejs\lib\ejs.js:272:36)
    at View.exports.renderFile [as engine] (C:\xampp\htdocs\sns_app\node_modules\ejs\lib\ejs.js:489:10)
    at View.render (C:\xampp\htdocs\sns_app\node_modules\express\lib\view.js:135:8)
    at tryRender (C:\xampp\htdocs\sns_app\node_modules\express\lib\application.js:640:10)
    at Function.render (C:\xampp\htdocs\sns_app\node_modules\express\lib\application.js:592:3)
    at ServerResponse.render (C:\xampp\htdocs\sns_app\node_modules\express\lib\response.js:1012:7)
    at Query.connection.query (C:\xampp\htdocs\sns_app\app.js:69:13)
    at Query.<anonymous> (C:\xampp\htdocs\sns_app\node_modules\mysql\lib\Connection.js:526:10)

該当のソースコード

<ul>
              <% tweets.forEach((tweet) => { %>
                <li class="tweet">
                  <span class="tweet_id"><%= tweet.id %></span>
                  <span class="tweet_content"><%= tweet.content %></span>
                  <% 
                    var category;
                    var list =["恋愛","科学","仕事","日常","広告","PC","病院","漫画","映画","ゲーム","政治"];
                    category = list[tweet.category];
                  %>
                  <span class="category">#<%= category %></span>
                  <form action="update_good" method="post">
                    <input type="hidden" name="tweet_id" value="<%= tweet.id %>">
                    <input type="submit" value="☆<%= tweet.good %>">
                  </form>
                </li><!--tweet-->
              <% }); %>
            </ul>

該当のソースコード

//mainページの表示
app.get('/main', (req, res) => {
    connection.query(
        'SELECT * FROM tweets',
    (error,results)=>{
        res.render('main.ejs',{user:username,tweets:results});
    });
});
//イイねボタンの更新
app.post('/update_good', (req, res) => {
    connection.query(
        'UPDATE tweets SET good WHERE id=?',
        [req.body.tweet_id],
    (error,results)=>{
        res.render('main.ejs',{user:username,tweets:results});
    });
});

試したこと

送信ボタンを押すと、このようなエラーを吐き出します。
表示をするだけなら、問題なくできております。

補足情報(FW/ツールのバージョンなど)

"dependencies": {
"ejs": "^3.1.5",
"express": "^4.17.1",
"jquery": "^3.5.1",
"mysql": "^2.18.1"
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Cannot read property 'forEach' of undefined

このエラー文は頻出なので覚えましょう。
まずはエラー文が何者なのかを説明します。

JSはオブジェクト指向プログラミング言語なので、
値はオブジェクトです。
オブジェクトはプロパティを所持することが許されています。

しかし、JSではプロパティの所持を許されていない
例外中の例外の値が2つ存在します

  • null
  • undefined

これらはプロパティの所持を許されていないどころか、
参照を試みただけでエラーで落ちてしまいます。
それがこのエラー。


さて、今回の質問を深堀りしましょう。

今回のエラー文を読み解きましょうか。
Cannot read property 'forEach' of undefinedでしたっけ。
なので直訳すればundefinedforEachプロパティを参照しようとしたのでエラー。

forEachがあるのはtweets.forEachの行ですね。
tweetsは配列であるべきだったのにundefinedが入っている事が問題です。
なぜtweetsが配列でないのか?に着目し、より上流の箇所を修正しましょう。

そういや「いいねボタン」押した時の挙動がおかしいんでしたっけ?
どれどれ?

//イイねボタンの更新
app.post('/update_good', (req, res) => {
    connection.query(
        'UPDATE tweets SET good WHERE id=?',
        [req.body.tweet_id],
    (error,results)=>{
        res.render('main.ejs',{user:username,tweets:results});
    });
});

'UPDATE tweets SET good WHERE id=?'のSQL文を送った結果がどうなるのか確認してみましたか?
これはUPDATEの結果テーブルがどうなったかの結果が得られるはずです。
tweetsテーブルの値の配列が入っているはずがないんですよ。

UPDATEに成功したら改めてSQLのSELECTを発行し
SELECTの結果をtweetsに束縛して使いましょう。

まぁこういったWebサーバを実装する上で、
Postの結果でHTMLを返す作りにするとF5キーでリロードする度にPostの処理が走るので微妙です。
リダイレクトさせるのが常套手段ですね。

Expressのリダイレクト機能を使って/パスのgetにリクエストを受け流す実装に変更しましょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/10/12 19:19

    redirectに修正すると、直りました!
    ご丁寧にありがとうございました!!

    キャンセル

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

  • ただいまの回答率 87.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る