@DocTypeMaster

Как решить ошибку Error in created hook: «TypeError: Cannot read property 'id' of undefined»?

Делал модуль комментариев с вложенностью, по уроку из ютуба, посты выводятся, а вот комментарии добавляются, но не выводятся.

Вот ошибка:
6135deff844ac504972889.png

[Vue warn]: Error in created hook: "TypeError: Cannot read property 'id' of undefined"

found in

---> <Post> at resources/js/components/Post.vue
       <Scrollable> at resources/js/components/Scrollable.vue
         <Posts> at resources/js/components/Posts.vue
           <Root>

Вот мои файлы:

Post.vue
<template>
  <div class="bg-white shadow p-4 rounded-lg mt-8">
      <div class="flex">

          <div class="ml-4 flex-1 flex flex-col justify-between">
              <h3 class="text-gray-700 text-2xl uppercase">
                  {{ post.title }}
                  <span class="text-gray-600 text-sm">{{ post.title }} years</span>
              </h3>

              <div><span class="bg-indigo-100 text-indigo-700 text-sm uppercase px-1 px-2 rounded-sm">{{ post.title }} </span></div>
          </div>
          <div class="flex flex-col justify-end">
              <button @click.prevent="showCommentsForm = ! showCommentsForm">
                  <svg class="stroke-current text-indigo-600 w-6" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
              </button>
          </div>
      </div>

      <!-- Comments -->
      <div v-show="showCommentsForm" class="mt-6">
          <div>
              <div class="relative">
                  <div class="absolute flex flex-col justify-center right-0 h-full px-4">
                      <button @click.prevent="postComment"><svg class="w-4 stroke-current text-indigo-500 hover:text-indigo-700" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg></button>
                  </div>
                  <input class="border border-indigo-200  hover:bg-indigo-100 focus:bg-indigo-100 outline-none pr-12 px-3 py-2 rounded text-sm w-full"
                         v-model="body"
                         placeholder="What do you think of this cat?"
                         @keyup.enter="postComment"
                  >
              </div>
              <!-- replying to -->
              <div v-show="replyingTo.id" class="flex items-center mt-2">
                  <div class="text-xs flex text-gray-600 uppercase mb-1">
                      <div class="flex items-center flex-none">
                          <button @click.prevent="unsetReplyingTo" class="mr-2"><svg class="stroke-current text-indigo-500 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="15" y1="9" x2="9" y2="15"></line><line x1="9" y1="9" x2="15" y2="15"></line></svg></button>
                          <span class="px-2 py-1 bg-gray-200">replying to: </span>
                      </div>
                      <div class="w-2/3 ml-4 pl-2 py-1 border-l-2 border-indigo-200 text-gray-600">
                          {{ replyingTo.body }}
                      </div>
                  </div>
              </div>
          </div>

          <!-- thread -->
          <div v-for="comment in comments" class="text-gray-700 py-4 pb-0 mt-4 rounded">
              <!-- parent comment -->
              <div class="-mx-4 px-4 bg-gray-100">
                  <span class="text-gray-500 uppercase text-xs">{{ comment.created_at }}</span>
                  <p>{{ comment.body }}</p>
                  <div>
                      <button @click.prevent="setReplyingTo(comment)"><svg class="stroke-current text-gray-500 w-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg></button>
                  </div>
              </div>
              <!-- replies -->
              <div v-for="reply in comment.replies" class="px-4">
                  <div class="text-gray-700 rounded">
                      <span class="text-gray-500 uppercase text-xs">{{ reply.created_at }}</span>
                      <p>{{ reply.body }}</p>
                      <div>
                          <button @click.prevent="setReplyingTo(comment)"><svg class="stroke-current text-gray-500 w-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg></button>
                      </div>
                  </div>
              </div>
          </div>
      </div>
  </div>
</template>

<script>
    export default {
        props: ['post'],
        data() {
            return {
                body: '',
                comments: [],
                showCommentsForm: false,
                replyingTo: {},
            }
        },
        methods: {
            postComment() {
                axios.post(`posts/${this.post.id}/comments`, {
                    parent_id: this.replyingTo.id ? this.replyingTo.id : null,
                    body: this.body,
                }).
                    then(response => {
                        this.body = ''
                        if (! this.replyingTo.id) {
                            this.comments.push(response.data)
                        } else {
                            this.replyingTo.replies.push(response.data)
                        }
                        this.unsetReplyingTo()
                    })
            },
            fetchComments() {
                axios.get(`posts/${this.posts.id}/comments`)
                    .then(response => {
                        this.comments = response.data
                    })
            },
            setReplyingTo(comment) {
                this.replyingTo = comment
            },
            unsetReplyingTo() {
                this.replyingTo = {}
            }
        },
        created() {
            this.fetchComments()
        }
    }
</script>

PostCommentsController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Post;

class PostCommentsController extends Controller
{
  public function index(Post $post)
      {
          $comments = $post->comments()->parent()->with('replies')->get();

          return response()->json($comments);
      }

      public function store(Request $request, Post $post)
      {
          $comment = $post->comments()->create([
              'parent_id' => $request->parent_id,
              'body' => $request->body,
          ]);

          return response()->json($comment);
      }
}


app\Models\Comment.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    public function scopeParent($query)
    {
        return $query->whereNull('parent_id');
    }

    public function replies()
    {
        return $this->hasMany(Comment::class, 'parent_id');
    }

    public function parent()
    {
        return $this->belongsTo(Comment::class);
    }
}

  • Вопрос задан
  • 185 просмотров
Решения вопроса 1
MrDecoy
@MrDecoy
Верставший фронтендер
Минутка обучения отладке:
0) Читаем текст ошибки. Видим что она из Post.vue.
1) Смотрим трэйс ошибки.
2) Видим что:
created -> fetchComponents -> cannot read id of undefined

3) Смотрим метод fetchComponents:
4) id используется только в одном месте
5) this.posts.id
6) Делаем вывод: this.posts во время выполнения метода = undefined
7) Смотрим что такое this.posts
8) Видим что такого не существует
9) А существует this.post (определено в props компонента)
10) Делаем вывод: опечатались или стали жертвой собственного копипаста и нужно в этом методе удалить лишнюю s.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы