Vue.js How to filtered out the ref by computed property

83 Views Asked by At

Tag.vue

<template>
  <div class="tag">
    Tag: {{ tag }}<br>
    <div v-if="error">{{ error }}</div>

    # {{ posts.length }}<br>
    # {{ computedFilteredList.length }}<br>
    <br>
    ============# {{ computedFilteredList.length }} computedFilteredList=================
    <div v-if="computedFilteredList.length">
      <PostList :posts="computedFilteredList"/>
    </div>
    <div v-else><Spinner/></div>
  </div>
</template>

<script>

import getPosts from "@/composables/getPosts";
import PostList from "@/components/PostList.vue";
import Spinner from "@/composables/Spinner.vue";
import {computed, ref} from "vue";
import {useRoute} from "vue-router";

export default {
  components: { Spinner, PostList },
  props: ['tag'],
  setup(){
    const { posts, error, load } = getPosts()
    load()

    const route = useRoute()
    console.log(posts.value.length)
    const computedFilteredList = computed(() => {
      return posts.value.filter((post) => {
        console.log(post)
        post.tags.includes(route.params.tag)
      })
    })
    return { posts, error, computedFilteredList }
  }
}
</script>

<style>

</style>

PostList.vue

<template>
  <div class="post-list">
    <div v-for="post in posts" :key="post.id">
      <SinglePost :post="post"/>
    </div>

  </div>
</template>

<script>

import SinglePost from "@/components/SinglePost.vue";
import {computed, onMounted, onUnmounted, onUpdated} from "vue";

export default {
  components: { SinglePost },
  props: ['posts'],
}
</script>

<style>

</style>

getPost.js

import {ref} from "vue";

const getPosts = () => {
  const posts = ref([])
  const error = ref(null)

  const load = async () => {
    try{
      // simulate delay
      // await new Promise(resolve => {
      //   setTimeout(resolve, 2000)
      // })

      let data = await fetch('http://localhost:3000/posts')
      if(!data.ok){
        throw Error('no data available')
      }
      posts.value = await data.json()
    }
    catch(err){
      error.value = err.message
      console.log(error.value)
    }
  }
  return { posts, error, load }
}

export default getPosts

db.json

{
  "posts": [
    {
      "id": 1,
      "title": "welcome to the new blog",
      "body": "rolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsum",
      "tags": [
        "webdev",
        "coding",
        "news"
      ]
    },
    {
      "id": 2,
      "title": "top 5 CSS tips",
      "body": "rolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsumrolrem iupsum",
      "tags": [
        "css",
        "webdev",
        "coding"
      ]
    },
    {
      "title": "test",
      "body": "test",
      "tags": [
        "rtet"
      ],
      "id": 3
    },
    {
      "title": "afdsa",
      "body": "asfads",
      "tags": [
        "fddsf",
        "asdf"
      ],
      "id": 4
    }
  ]
}

Update: When I try create project with > npm create vue@latest I got new problem.

Uncaught ReferenceError: Cannot access 'PostList' before initialization at Tag.vue:26:26

Warning: Failed to resolve component: PostList If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.

Problem: Computed property has no result.

Question: Where am I wrong. I got this code from Udemy class. Some of the student got the same question 2 years ago and no one answer to them.

1

There are 1 best solutions below

0
On BEST ANSWER

Array.filter callback function should return a true/false value. This boolean tells the filter whether or not to include the object in the resulting filtered array. If you don't return a boolean, the filter won't do any filtering at all. In summary, add a return statement to your filter:

const computedFilteredList = computed(() => {
  return posts.value.filter(post => {
    console.log(post)
    return post.tags.includes(route.params.tag) // return this result
  })
})

If you can write your filter function as one line, without function braces {}, the return value can be implied. This would involve removing the console log:

const computedFilteredList = computed(() => {
  return posts.value.filter(post => post.tags.includes(route.params.tag))
})